root / ImageMagick / trunk / wand / mogrify.c

Revision 12087, 236.8 kB (checked in by cristy, 39 hours ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%              M   M   OOO   GGGGG  RRRR   IIIII  FFFFF  Y   Y                %
7%              MM MM  O   O  G      R   R    I    F       Y Y                 %
8%              M M M  O   O  G GGG  RRRR     I    FFF      Y                  %
9%              M   M  O   O  G   G  R R      I    F        Y                  %
10%              M   M   OOO   GGGG   R  R   IIIII  F        Y                  %
11%                                                                             %
12%                                                                             %
13%                        ImageMagick Module Methods                           %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                March 2000                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "wand/studio.h"
44#include "wand/MagickWand.h"
45#include "wand/mogrify-private.h"
46
47/*
48  Define declarations.
49*/
50#define UndefinedCompressionQuality  0UL
51
52/*
53  Constant declaration.
54*/
55static const char
56  *BackgroundColor = "#fff"/* white */
57  *BorderColor = "#dfdfdf"/* gray */
58  *MatteColor = "#bdbdbd"/* gray */
59
60/*
61%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62%                                                                             %
63%                                                                             %
64%                                                                             %
65+     M o g r i f y I m a g e                                                 %
66%                                                                             %
67%                                                                             %
68%                                                                             %
69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70%
71%  MogrifyImage() applies image processing options to an image as prescribed
72%  by command line options.
73%
74%  The format of the MogrifyImage method is:
75%
76%      MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
77%        const char **argv,Image **image)
78%
79%  A description of each parameter follows:
80%
81%    o image_info: the image info..
82%
83%    o argc: Specifies a pointer to an integer describing the number of
84%      elements in the argument vector.
85%
86%    o argv: Specifies a pointer to a text array containing the command line
87%      arguments.
88%
89%    o image: the image.
90%
91%    o exception: Return any errors or warnings in this structure.
92%
93*/
94
95static int IsDirectory(const char *path)
96{
97#if !defined(X_OK)
98#define X_OK  1
99#endif
100
101  int
102    status;
103
104  struct stat
105    file_info;
106
107  if ((path == (const char *) NULL) || (*path == '\0'))
108    return(MagickFalse);
109  status=stat(path,&file_info);
110  if (status != 0)
111    return(-1);
112  if (S_ISDIR(file_info.st_mode) == 0)
113    return(0);
114  if (access(path,X_OK) != 0)
115    return(0);
116  return(1);
117}
118
119static inline long MagickMax(const long x,const long y)
120{
121  if (x > y)
122    return(x);
123  return(y);
124}
125
126static MagickBooleanType MonitorProgress(const char *tag,
127  const MagickOffsetType quantum,const MagickSizeType span,
128  void *wand_unused(client_data))
129{
130  char
131    message[MaxTextExtent];
132
133  const char
134    *locale_message;
135
136  if (span < 2)
137    return(MagickTrue);
138  (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
139  locale_message=GetLocaleMessage(message);
140  if (locale_message == message)
141    locale_message=tag;
142  (void) fprintf(stderr,"%s: %02ld%%\r",locale_message,(long)
143    (100L*quantum/(span-1)));
144  if ((MagickSizeType) quantum == (span-1))
145    (void) fprintf(stderr,"\n");
146  (void) fflush(stderr);
147  return(MagickTrue);
148}
149
150WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
151  const char **argv,Image **image,ExceptionInfo *exception)
152{
153  const char
154    *format,
155    *option;
156
157  DrawInfo
158    *draw_info;
159
160  GeometryInfo
161    geometry_info;
162
163  Image
164    *region_image;
165
166  long
167    count;
168
169  MagickBooleanType
170    status;
171
172  MagickPixelPacket
173    fill;
174
175  MagickStatusType
176    flags;
177
178  QuantizeInfo
179    *quantize_info;
180
181  RectangleInfo
182    geometry,
183    region_geometry;
184
185  register long
186    i;
187
188  /*
189    Initialize method variables.
190  */
191  assert(image_info != (const ImageInfo *) NULL);
192  assert(image_info->signature == MagickSignature);
193  assert(image != (Image **) NULL);
194  assert((*image)->signature == MagickSignature);
195  if ((*image)->debug != MagickFalse)
196    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
197  if (argc < 0)
198    return(MagickTrue);
199  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
200  quantize_info=AcquireQuantizeInfo(image_info);
201  SetGeometryInfo(&geometry_info);
202  GetMagickPixelPacket(*image,&fill);
203  SetMagickPixelPacket(*image,&(*image)->background_color,(IndexPacket *) NULL,
204    &fill);
205  format=GetImageOption(image_info,"format");
206  SetGeometry(*image,&region_geometry);
207  region_image=NewImageList();
208  /*
209    Transmogrify the image.
210  */
211  for (i=0; i < (long) argc; i++)
212  {
213    option=argv[i];
214    if (IsMagickOption(option) == MagickFalse)
215      continue;
216    count=MagickMax(ParseMagickOption(MagickCommandOptions,MagickFalse,option),
217      0L);
218    if ((i+count) >= argc)
219      break;
220    status=MogrifyImageInfo(image_info,count+1,argv+i,exception);
221    switch (*(option+1))
222    {
223      case 'a':
224      {
225        if (LocaleCompare("adaptive-blur",option+1) == 0)
226          {
227            Image
228              *blur_image;
229
230            /*
231              Blur image.
232            */
233            flags=ParseGeometry(argv[i+1],&geometry_info);
234            if ((flags & SigmaValue) == 0)
235              geometry_info.sigma=1.0;
236            blur_image=AdaptiveBlurImageChannel(*image,image_info->channel,
237              geometry_info.rho,geometry_info.sigma,exception);
238            if (blur_image == (Image *) NULL)
239              break;
240            *image=DestroyImage(*image);
241            *image=blur_image;
242            break;
243          }
244        if (LocaleCompare("adaptive-resize",option+1) == 0)
245          {
246            Image
247              *resize_image;
248
249            /*
250              Resize image.
251            */
252            (void) ParseSizeGeometry(*image,argv[i+1],&geometry);
253            resize_image=AdaptiveResizeImage(*image,geometry.width,
254              geometry.height,exception);
255            if (resize_image == (Image *) NULL)
256              break;
257            *image=DestroyImage(*image);
258            *image=resize_image;
259            break;
260          }
261        if (LocaleCompare("adaptive-sharpen",option+1) == 0)
262          {
263            Image
264              *sharp_image;
265
266            /*
267              Sharpen image.
268            */
269            flags=ParseGeometry(argv[i+1],&geometry_info);
270            if ((flags & SigmaValue) == 0)
271              geometry_info.sigma=1.0;
272            sharp_image=AdaptiveSharpenImageChannel(*image,image_info->channel,
273              geometry_info.rho,geometry_info.sigma,exception);
274            if (sharp_image == (Image *) NULL)
275              break;
276            *image=DestroyImage(*image);
277            *image=sharp_image;
278            break;
279          }
280        if (LocaleCompare("affine",option+1) == 0)
281          {
282            /*
283              Affine matrix.
284            */
285            if (*option == '+')
286              {
287                GetAffineMatrix(&draw_info->affine);
288                break;
289              }
290            (void) ParseAffineGeometry(argv[i+1],&draw_info->affine);
291            break;
292          }
293        if (LocaleCompare("alpha",option+1) == 0)
294          {
295            AlphaChannelType
296              alpha_type;
297
298            alpha_type=(AlphaChannelType) ParseMagickOption(MagickAlphaOptions,
299              MagickFalse,argv[i+1]);
300            (void) SetImageAlphaChannel(*image,alpha_type);
301            InheritException(exception,&(*image)->exception);
302            break;
303          }
304        if (LocaleCompare("annotate",option+1) == 0)
305          {
306            char
307              geometry[MaxTextExtent];
308
309            /*
310              Annotate image.
311            */
312            SetGeometryInfo(&geometry_info);
313            flags=ParseGeometry(argv[i+1],&geometry_info);
314            if ((flags & SigmaValue) == 0)
315              geometry_info.sigma=geometry_info.rho;
316            (void) CloneString(&draw_info->text,InterpretImageProperties(
317              image_info,*image,argv[i+2]));
318            (void) FormatMagickString(geometry,MaxTextExtent,"%+f%+f",
319              geometry_info.xi,geometry_info.psi);
320            (void) CloneString(&draw_info->geometry,geometry);
321            draw_info->affine.sx=cos(DegreesToRadians(
322              fmod(geometry_info.rho,360.0)));
323            draw_info->affine.rx=sin(DegreesToRadians(
324              fmod(geometry_info.rho,360.0)));
325            draw_info->affine.ry=(-sin(DegreesToRadians(
326              fmod(geometry_info.sigma,360.0))));
327            draw_info->affine.sy=cos(DegreesToRadians(
328              fmod(geometry_info.sigma,360.0)));
329            (void) AnnotateImage(*image,draw_info);
330            InheritException(exception,&(*image)->exception);
331            break;
332          }
333        if (LocaleCompare("antialias",option+1) == 0)
334          {
335            draw_info->stroke_antialias=(*option == '-') ? MagickTrue :
336              MagickFalse;
337            draw_info->text_antialias=(*option == '-') ? MagickTrue :
338              MagickFalse;
339            break;
340          }
341        if (LocaleCompare("attenuate",option+1) == 0)
342          {
343            (void) SetImageOption(image_info,option+1,argv[i+1]);
344            break;
345          }
346        if (LocaleCompare("auto-orient",option+1) == 0)
347          {
348            Image
349              *orient_image;
350
351            orient_image=NewImageList();
352            switch ((*image)->orientation)
353            {
354              case TopRightOrientation:
355              {
356                orient_image=FlopImage(*image,exception);
357                break;
358              }
359              case BottomRightOrientation:
360              {
361                orient_image=RotateImage(*image,180.0,exception);
362                break;
363              }
364              case BottomLeftOrientation:
365              {
366                orient_image=FlipImage(*image,exception);
367                break;
368              }
369              case LeftTopOrientation:
370              {
371                orient_image=TransposeImage(*image,exception);
372                break;
373              }
374              case RightTopOrientation:
375              {
376                orient_image=RotateImage(*image,90.0,exception);
377                break;
378              }
379              case RightBottomOrientation:
380              {
381                orient_image=TransverseImage(*image,exception);
382                break;
383              }
384              case LeftBottomOrientation:
385              {
386                orient_image=RotateImage(*image,270.0,exception);
387                break;
388              }
389              default:
390                break;
391            }
392            if (orient_image == (Image *) NULL)
393              break;
394            orient_image->orientation=TopLeftOrientation;
395            *image=DestroyImage(*image);
396            *image=orient_image;
397            break;
398          }
399        break;
400      }
401      case 'b':
402      {
403        if (LocaleCompare("background",option+1) == 0)
404          {
405            if (*option == '+')
406              {
407                (void) QueryColorDatabase(BackgroundColor,
408                  &(*image)->background_color,exception);
409                break;
410              }
411            (void) QueryColorDatabase(argv[i+1],&(*image)->background_color,
412              exception);
413            break;
414          }
415        if (LocaleCompare("black-threshold",option+1) == 0)
416          {
417            /*
418              Threshold black image.
419            */
420            (void) BlackThresholdImage(*image,argv[i+1]);
421            InheritException(exception,&(*image)->exception);
422            break;
423          }
424        if (LocaleCompare("black-point-compensation",option+1) == 0)
425          {
426            (*image)->black_point_compensation=(*option == '-') ? MagickTrue :
427              MagickFalse;
428            break;
429          }
430        if (LocaleCompare("blue-primary",option+1) == 0)
431          {
432            /*
433              Blue chromaticity primary point.
434            */
435            if (*option == '+')
436              {
437                (*image)->chromaticity.blue_primary.x=0.0;
438                (*image)->chromaticity.blue_primary.y=0.0;
439                break;
440              }
441            flags=ParseGeometry(argv[i+1],&geometry_info);
442            (*image)->chromaticity.blue_primary.x=geometry_info.rho;
443            (*image)->chromaticity.blue_primary.y=geometry_info.sigma;
444            if ((flags & SigmaValue) == 0)
445              (*image)->chromaticity.blue_primary.y=
446                (*image)->chromaticity.blue_primary.x;
447            break;
448          }
449        if (LocaleCompare("blur",option+1) == 0)
450          {
451            Image
452              *blur_image;
453
454            /*
455              Gaussian blur image.
456            */
457            flags=ParseGeometry(argv[i+1],&geometry_info);
458            if ((flags & SigmaValue) == 0)
459              geometry_info.sigma=1.0;
460            blur_image=BlurImageChannel(*image,image_info->channel,
461              geometry_info.rho,geometry_info.sigma,exception);
462            if (blur_image == (Image *) NULL)
463              break;
464            *image=DestroyImage(*image);
465            *image=blur_image;
466            break;
467          }
468        if (LocaleCompare("border",option+1) == 0)
469          {
470            Image
471              *border_image;
472
473            /*
474              Surround image with a border of solid color.
475            */
476            flags=ParsePageGeometry(*image,argv[i+1],&geometry);
477            if ((flags & SigmaValue) == 0)
478              geometry.height=geometry.width;
479            border_image=BorderImage(*image,&geometry,exception);
480            if (border_image == (Image *) NULL)
481              break;
482            *image=DestroyImage(*image);
483            *image=border_image;
484            break;
485          }
486        if (LocaleCompare("bordercolor",option+1) == 0)
487          {
488            if (*option == '+')
489              {
490                (void) QueryColorDatabase(BorderColor,&(*image)->border_color,
491                  exception);
492                draw_info->border_color=(*image)->border_color;
493                break;
494              }
495            (void) QueryColorDatabase(argv[i+1],&(*image)->border_color,
496              exception);
497            draw_info->border_color=(*image)->border_color;
498            break;
499          }
500        if (LocaleCompare("box",option+1) == 0)
501          {
502            (void) QueryColorDatabase(argv[i+1],&draw_info->undercolor,
503              exception);
504            break;
505          }
506        break;
507      }
508      case 'c':
509      {
510        if (LocaleCompare("channel",option+1) == 0)
511          {
512            if (*option == '+')
513              {
514                image_info->channel=DefaultChannels;
515                break;
516              }
517            image_info->channel=(ChannelType) ParseChannelOption(argv[i+1]);
518            break;
519          }
520        if (LocaleCompare("charcoal",option+1) == 0)
521          {
522            Image
523              *charcoal_image;
524
525            /*
526              Charcoal image.
527            */
528            flags=ParseGeometry(argv[i+1],&geometry_info);
529            if ((flags & SigmaValue) == 0)
530              geometry_info.sigma=1.0;
531            charcoal_image=CharcoalImage(*image,geometry_info.rho,
532              geometry_info.sigma,exception);
533            if (charcoal_image == (Image *) NULL)
534              break;
535            *image=DestroyImage(*image);
536            *image=charcoal_image;
537            break;
538          }
539        if (LocaleCompare("chop",option+1) == 0)
540          {
541            Image
542              *chop_image;
543
544            /*
545              Chop the image.
546            */
547            (void) ParseGravityGeometry(*image,argv[i+1],&geometry);
548            chop_image=ChopImage(*image,&geometry,exception);
549            if (chop_image == (Image *) NULL)
550              break;
551            *image=DestroyImage(*image);
552            *image=chop_image;
553            break;
554          }
555        if (LocaleCompare("clip",option+1) == 0)
556          {
557            if (*option == '+')
558              {
559                (void) SetImageClipMask(*image,(Image *) NULL);
560                InheritException(exception,&(*image)->exception);
561                break;
562              }
563            (void) ClipImage(*image);
564            InheritException(exception,&(*image)->exception);
565            break;
566          }
567        if (LocaleCompare("clip-mask",option+1) == 0)
568          {
569            Image
570              *mask;
571
572            ImageInfo
573              *mask_info;
574
575            long
576              y;
577
578            register long
579              x;
580
581            register PixelPacket
582              *q;
583
584            if (*option == '+')
585              {
586                /*
587                  Remove a mask.
588                */
589                (void) SetImageMask(*image,(Image *) NULL);
590                InheritException(exception,&(*image)->exception);
591                break;
592              }
593            /*
594              Set the image mask.
595            */
596            mask_info=CloneImageInfo(image_info);
597            (void) CopyMagickString(mask_info->filename,argv[i+1],
598              MaxTextExtent);
599            mask=ReadImage(mask_info,exception);
600            CatchException(exception);
601            mask_info=DestroyImageInfo(mask_info);
602            if (mask == (Image *) NULL)
603              break;
604            for (y=0; y < (long) mask->rows; y++)
605            {
606              q=GetImagePixels(mask,0,y,mask->columns,1);
607              if (q == (PixelPacket *) NULL)
608                break;
609              for (x=0; x < (long) mask->columns; x++)
610              {
611                if (mask->matte == MagickFalse)
612                  q->opacity=PixelIntensityToQuantum(q);
613                q->red=q->opacity;
614                q->green=q->opacity;
615                q->blue=q->opacity;
616                q++;
617              }
618              if (SyncImagePixels(mask) == MagickFalse)
619                break;
620            }
621            if (SetImageStorageClass(mask,DirectClass) == MagickFalse)
622              return(MagickFalse);
623            mask->matte=MagickTrue;
624            (void) SetImageClipMask(*image,mask);
625            InheritException(exception,&(*image)->exception);
626            break;
627          }
628        if (LocaleCompare("clip-path",option+1) == 0)
629          {
630            (void) ClipImagePath(*image,argv[i+1],
631              *option == '-' ? MagickTrue : MagickFalse);
632            InheritException(exception,&(*image)->exception);
633            break;
634          }
635        if (LocaleCompare("colorize",option+1) == 0)
636          {
637            Image
638              *colorize_image;
639
640            /*
641              Colorize the image.
642            */
643            colorize_image=ColorizeImage(*image,argv[i+1],draw_info->fill,
644              exception);
645            if (colorize_image == (Image *) NULL)
646              break;
647            *image=DestroyImage(*image);
648            *image=colorize_image;
649            break;
650          }
651        if (LocaleCompare("colors",option+1) == 0)
652          {
653            /*
654              Reduce the number of colors in the image.
655            */
656            quantize_info->number_colors=(unsigned long) atol(argv[i+1]);
657            if (quantize_info->number_colors == 0)
658              break;
659            if (((*image)->storage_class == DirectClass) ||
660                (*image)->colors > quantize_info->number_colors)
661              (void) QuantizeImage(quantize_info,*image);
662            else
663              (void) CompressImageColormap(*image);
664            InheritException(exception,&(*image)->exception);
665            break;
666          }
667        if (LocaleCompare("colorspace",option+1) == 0)
668          {
669            ColorspaceType
670              colorspace;
671
672            if (*option == '+')
673              {
674                (void) SetImageColorspace(*image,RGBColorspace);
675                InheritException(exception,&(*image)->exception);
676                break;
677              }
678            colorspace=(ColorspaceType) ParseMagickOption(
679              MagickColorspaceOptions,MagickFalse,argv[i+1]);
680            (void) SetImageColorspace(*image,colorspace);
681            InheritException(exception,&(*image)->exception);
682            break;
683          }
684        if (LocaleCompare("contrast",option+1) == 0)
685          {
686            (void) ContrastImage(*image,(*option == '-') ? MagickTrue :
687              MagickFalse);
688            InheritException(exception,&(*image)->exception);
689            break;
690          }
691        if (LocaleCompare("contrast-stretch",option+1) == 0)
692          {
693            double
694              black_point,
695              white_point;
696
697            GeometryInfo
698              geometry_info;
699
700            MagickStatusType
701              flags;
702
703            /*
704              Parse levels.
705            */
706            flags=ParseGeometry(argv[i+1],&geometry_info);
707            black_point=geometry_info.rho;
708            white_point=(MagickRealType) (*image)->columns*(*image)->rows;
709            if ((flags & SigmaValue) != 0)
710              white_point=geometry_info.sigma;
711            if ((flags & PercentValue) != 0)
712              {
713                black_point*=(double) (*image)->columns*(*image)->rows/100.0;
714                white_point*=(double) (*image)->columns*(*image)->rows/100.0;
715              }
716            if ((flags & SigmaValue) == 0)
717              white_point=(MagickRealType) (*image)->columns*(*image)->rows-
718                black_point;
719            (void) ContrastStretchImageChannel(*image,image_info->channel,
720              black_point,white_point);
721            InheritException(exception,&(*image)->exception);
722            break;
723          }
724        if (LocaleCompare("convolve",option+1) == 0)
725          {
726            char
727              token[MaxTextExtent];
728
729            const char
730              *p;
731
732            double
733              *kernel;
734
735            Image
736              *convolve_image;
737
738            register long
739              x;
740
741            unsigned long
742              order;
743
744            /*
745              Convolve image.
746            */
747            p=(char *) argv[i+1];
748            for (x=0; *p != '\0'; x++)
749            {
750              GetMagickToken(p,&p,token);
751              if (*token == ',')
752                GetMagickToken(p,&p,token);
753            }
754            order=(unsigned long) sqrt((double) x+1.0);
755            kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
756            if (kernel == (double *) NULL)
757              ThrowWandFatalException(ResourceLimitFatalError,
758                "MemoryAllocationFailed",(*image)->filename);
759            p=(char *) argv[i+1];
760            for (x=0; (x < (long) (order*order)) && (*p != '\0'); x++)
761            {
762              GetMagickToken(p,&p,token);
763              if (*token == ',')
764                GetMagickToken(p,&p,token);
765              kernel[x]=atof(token);
766            }
767            for ( ; x < (long) (order*order); x++)
768              kernel[x]=0.0;
769            convolve_image=ConvolveImageChannel(*image,image_info->channel,
770              order,kernel,exception);
771            kernel=(double *) RelinquishMagickMemory(kernel);
772            if (convolve_image == (Image *) NULL)
773              break;
774            *image=DestroyImage(*image);
775            *image=convolve_image;
776            break;
777          }
778        if (LocaleCompare("crop",option+1) == 0)
779          {
780            if (*option == '+')
781              break;
782            break;
783          }
784        if (LocaleCompare("cycle",option+1) == 0)
785          {
786            /*
787              Cycle an image colormap.
788            */
789            (void) CycleColormapImage(*image,atoi(argv[i+1]));
790            InheritException(exception,&(*image)->exception);
791            break;
792          }
793        break;
794      }
795      case 'd':
796      {
797        if (LocaleCompare("decipher",option+1) == 0)
798          {
799            char
800              *passphrase;
801
802            /*
803              Decipher pixels.
804            */
805            passphrase=FileToString(argv[i+1],~0,exception);
806            if (passphrase != (char *) NULL)
807              {
808                (void) DecipherImage(*image,passphrase,exception);
809                passphrase=DestroyString(passphrase);
810              }
811            break;
812          }
813        if (LocaleCompare("density",option+1) == 0)
814          {
815            GeometryInfo
816              geometry_info;
817
818            /*
819              Set image density.
820            */
821            (void) CloneString(&draw_info->density,argv[i+1]);
822            flags=ParseGeometry(argv[i+1],&geometry_info);
823            (*image)->x_resolution=geometry_info.rho;
824            (*image)->y_resolution=geometry_info.sigma;
825            if ((flags & SigmaValue) == 0)
826              (*image)->y_resolution=(*image)->x_resolution;
827            break;
828          }
829        if (LocaleCompare("deskew",option+1) == 0)
830          {
831            double
832              threshold;
833
834            Image
835              *deskew_image;
836
837            /*
838              Straighten the image.
839            */
840            if (*option == '+')
841              threshold=40.0*QuantumRange/100.0;
842            else
843              threshold=StringToDouble(argv[i+1],QuantumRange);
844            deskew_image=DeskewImage(*image,threshold,exception);
845            if (deskew_image == (Image *) NULL)
846              break;
847            *image=DestroyImage(*image);
848            *image=deskew_image;
849            break;
850          }
851        if (LocaleCompare("despeckle",option+1) == 0)
852          {
853            Image
854              *despeckle_image;
855
856            /*
857              Reduce the speckles within an image.
858            */
859            despeckle_image=DespeckleImage(*image,exception);
860            if (despeckle_image == (Image *) NULL)
861              break;
862            *image=DestroyImage(*image);
863            *image=despeckle_image;
864            break;
865          }
866        if (LocaleCompare("display",option+1) == 0)
867          {
868            (void) CloneString(&draw_info->server_name,argv[i+1]);
869            break;
870          }
871        if (LocaleCompare("distort",option+1) == 0)
872          {
873            char
874              token[MaxTextExtent];
875
876            const char
877              *p;
878
879            DistortImageMethod
880              method;
881
882            double
883              *arguments;
884
885            Image
886              *distort_image;
887
888            register long
889              x;
890
891            unsigned long
892              number_arguments;
893
894            /*
895              Distort image.
896            */
897            method=(DistortImageMethod) ParseMagickOption(MagickDistortOptions,
898              MagickFalse,argv[i+1]);
899            p=(char *) argv[i+2];
900            for (x=0; *p != '\0'; x++)
901            {
902              GetMagickToken(p,&p,token);
903              if (*token == ',')
904                GetMagickToken(p,&p,token);
905            }
906            number_arguments=1UL*x;
907            arguments=(double *) AcquireQuantumMemory(number_arguments,
908              sizeof(*arguments));
909            if (arguments == (double *) NULL)
910              ThrowWandFatalException(ResourceLimitFatalError,
911                "MemoryAllocationFailed",(*image)->filename);
912            (void) ResetMagickMemory(arguments,0,number_arguments*
913               sizeof(*arguments));
914            p=(char *) argv[i+2];
915            for (x=0; (x < (long) number_arguments) && (*p != '\0'); x++)
916            {
917              GetMagickToken(p,&p,token);
918              if (*token == ',')
919                GetMagickToken(p,&p,token);
920              arguments[x]=atof(token);
921            }
922            distort_image=DistortImage(*image,method,number_arguments,
923              arguments,((*option == '+') ? MagickTrue : MagickFalse),
924              exception);
925            arguments=(double *) RelinquishMagickMemory(arguments);
926            if (distort_image == (Image *) NULL)
927              break;
928            *image=DestroyImage(*image);
929            *image=distort_image;
930            break;
931          }
932        if (LocaleCompare("dither",option+1) == 0)
933          {
934            if (*option == '+')
935              {
936                quantize_info->dither=MagickFalse;
937                break;
938              }
939            quantize_info->dither=MagickTrue;
940            quantize_info->dither_method=(DitherMethod) ParseMagickOption(
941              MagickDitherOptions,MagickFalse,argv[i+1]);
942            break;
943          }
944        if (LocaleCompare("draw",option+1) == 0)
945          {
946            /*
947              Draw image.
948            */
949            (void) CloneString(&draw_info->primitive,argv[i+1]);
950            (void) DrawImage(*image,draw_info);
951            InheritException(exception,&(*image)->exception);
952            break;
953          }
954        break;
955      }
956      case 'e':
957      {
958        if (LocaleCompare("edge",option+1) == 0)
959          {
960            Image
961              *edge_image;
962
963            /*
964              Enhance edges in the image.
965            */
966            flags=ParseGeometry(argv[i+1],&geometry_info);
967            if ((flags & SigmaValue) == 0)
968              geometry_info.sigma=1.0;
969            edge_image=EdgeImage(*image,geometry_info.rho,exception);
970            if (edge_image == (Image *) NULL)
971              break;
972            *image=DestroyImage(*image);
973            *image=edge_image;
974            break;
975          }
976        if (LocaleCompare("emboss",option+1) == 0)
977          {
978            Image
979              *emboss_image;
980
981            /*
982              Gaussian embossen image.
983            */
984            flags=ParseGeometry(argv[i+1],&geometry_info);
985            if ((flags & SigmaValue) == 0)
986              geometry_info.sigma=1.0;
987            emboss_image=EmbossImage(*image,geometry_info.rho,
988              geometry_info.sigma,exception);
989            if (emboss_image == (Image *) NULL)
990              break;
991            *image=DestroyImage(*image);
992            *image=emboss_image;
993            break;
994          }
995        if (LocaleCompare("encipher",option+1) == 0)
996          {
997            char
998              *passphrase;
999
1000            /*
1001              Encipher pixels.
1002            */
1003            passphrase=FileToString(argv[i+1],~0,exception);
1004            if (passphrase != (char *) NULL)
1005              {
1006                (void) EncipherImage(*image,passphrase,exception);
1007                passphrase=DestroyString(passphrase);
1008              }
1009            break;
1010          }
1011        if (LocaleCompare("encoding",option+1) == 0)
1012          {
1013            (void) CloneString(&draw_info->encoding,argv[i+1]);
1014            break;
1015          }
1016        if (LocaleCompare("enhance",option+1) == 0)
1017          {
1018            Image
1019              *enhance_image;
1020
1021            /*
1022              Enhance image.
1023            */
1024            enhance_image=EnhanceImage(*image,exception);
1025            if (enhance_image == (Image *) NULL)
1026              break;
1027            *i