root / ImageMagick / trunk / wand / stream.c

Revision 12434, 24.6 kB (checked in by cristy, 3 weeks ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                 SSSSS  TTTTT  RRRR   EEEEE   AAA   M   M                    %
7%                 SS       T    R   R  E      A   A  MM MM                    %
8%                  SSS     T    RRRR   EEE    AAAAA  M M M                    %
9%                    SS    T    R R    E      A   A  M   M                    %
10%                 SSSSS    T    R  R   EEEEE  A   A  M   M                    %
11%                                                                             %
12%                                                                             %
13%                     Stream image to a raw image format.                     %
14%                                                                             %
15%                           Software Design                                   %
16%                             John Cristy                                     %
17%                              July 1992                                      %
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%  Use Stream is a lightweight utility designed to extract pixels from large
37%  image files to a raw format using a minimum of system resources.  The
38%  entire image or any regular portion of the image can be extracted.
39%
40%
41*/
42
43/*
44  Include declarations.
45*/
46#include "wand/studio.h"
47#include "wand/MagickWand.h"
48#include "wand/mogrify-private.h"
49#include "magick/stream-private.h"
50
51/*
52%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53%                                                                             %
54%                                                                             %
55%                                                                             %
56%   S t r e a m I m a g e C o m m a n d                                       %
57%                                                                             %
58%                                                                             %
59%                                                                             %
60%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61%
62%  StreamImageCommand() is a lightweight method designed to extract pixels
63%  from large image files to a raw format using a minimum of system resources.
64%  The entire image or any regular portion of the image can be extracted.
65%
66%  The format of the StreamImageCommand method is:
67%
68%      MagickBooleanType StreamImageCommand(ImageInfo *image_info,int argc,
69%        char **argv,char **metadata,ExceptionInfo *exception)
70%
71%  A description of each parameter follows:
72%
73%    o image_info: the image info.
74%
75%    o argc: the number of elements in the argument vector.
76%
77%    o argv: A text array containing the command line arguments.
78%
79%    o metadata: any metadata is returned here.
80%
81%    o exception: Return any errors or warnings in this structure.
82%
83%
84*/
85
86static void StreamUsage(void)
87{
88  const char
89    **p;
90
91  static const char
92    *miscellaneous[]=
93    {
94      "-debug events        display copious debugging information",
95      "-help                print program options",
96      "-list type           print a list of supported option arguments",
97      "-log format          format of debugging information",
98      "-version             print version information",
99      (char *) NULL
100    },
101    *settings[]=
102    {
103      "-authenticate password",
104      "                     decipher image with this password",
105      "-channel type        apply option to select image channels",
106      "-colorspace type     alternate image colorspace",
107      "-compress type       type of pixel compression when writing the image",
108      "-define format:option",
109      "                     define one or more image format options",
110      "-density geometry    horizontal and vertical density of the image",
111      "-depth value         image depth",
112      "-extract geometry    extract area from image",
113      "-identify            identify the format and characteristics of the image",
114      "-interlace type      type of image interlacing scheme",
115      "-interpolate method  pixel color interpolation method",
116      "-limit type value    pixel cache resource limit",
117      "-map components      one or more pixel components",
118      "-monitor             monitor progress",
119      "-quantize colorspace reduce colors in this colorspace",
120      "-quiet               suppress all warning messages",
121      "-regard-warnings     pay attention to warning messages",
122      "-respect-parenthesis settings remain in effect until parenthesis boundary",
123      "-sampling-factor geometry",
124      "                     horizontal and vertical sampling factor",
125      "-seed value          seed a new sequence of pseudo-random numbers",
126      "-set attribute value set an image attribute",
127      "-size geometry       width and height of image",
128      "-storage-type type   pixel storage type",
129      "-transparent-color color",
130      "                     transparent color",
131      "-verbose             print detailed information about the image",
132      "-virtual-pixel method",
133      "                     virtual pixel access method",
134      (char *) NULL
135    };
136
137  (void) printf("Version: %s\n",GetMagickVersion((unsigned long *) NULL));
138  (void) printf("Copyright: %s\n\n",GetMagickCopyright());
139  (void) printf("Usage: %s [options ...] input-image raw-image\n",
140    GetClientName());
141  (void) printf("\nImage Settings:\n");
142  for (p=settings; *p != (char *) NULL; p++)
143    (void) printf("  %s\n",*p);
144  (void) printf("\nMiscellaneous Options:\n");
145  for (p=miscellaneous; *p != (char *) NULL; p++)
146    (void) printf("  %s\n",*p);
147  (void) printf(
148    "\nBy default, the image format of `file' is determined by its magic\n");
149  (void) printf(
150    "number.  To specify a particular image format, precede the filename\n");
151  (void) printf(
152    "with an image format name and a colon (i.e. ps:image) or specify the\n");
153  (void) printf(
154    "image type as the filename suffix (i.e. image.ps).  Specify 'file' as\n");
155  (void) printf("'-' for standard input or output.\n");
156  exit(0);
157}
158
159WandExport MagickBooleanType StreamImageCommand(ImageInfo *image_info,
160  int argc,char **argv,char **metadata,ExceptionInfo *exception)
161{
162#define DestroyStream() \
163{ \
164  DestroyImageStack(); \
165  stream_info=DestroyStreamInfo(stream_info); \
166  for (i=0; i < (long) argc; i++) \
167    argv[i]=DestroyString(argv[i]); \
168  argv=(char **) RelinquishMagickMemory(argv); \
169}
170#define ThrowStreamException(asperity,tag,option) \
171{ \
172  (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
173    option); \
174  DestroyStream(); \
175  return(MagickFalse); \
176}
177#define ThrowStreamInvalidArgumentException(option,argument) \
178{ \
179  (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
180    "InvalidArgument","`%s': %s",argument,option); \
181  DestroyStream(); \
182  return(MagickFalse); \
183}
184
185  char
186    *filename,
187    *option;
188
189  const char
190    *format;
191
192  Image
193    *image;
194
195  ImageStack
196    image_stack[MaxImageStackDepth+1];
197
198  long
199    j,
200    k;
201
202  MagickBooleanType
203    fire,
204    pend;
205
206  MagickStatusType
207    status;
208
209  register long
210    i;
211
212  StreamInfo
213    *stream_info;
214
215  /*
216    Set defaults.
217  */
218  assert(image_info != (ImageInfo *) NULL);
219  assert(image_info->signature == MagickSignature);
220  if (image_info->debug != MagickFalse)
221    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
222  assert(exception != (ExceptionInfo *) NULL);
223  (void) metadata;
224  if (argc == 2)
225    {
226      option=argv[1];
227      if ((LocaleCompare("version",option+1) == 0) ||
228          (LocaleCompare("-version",option+1) == 0))
229        {
230          (void) fprintf(stdout,"Version: %s\n",
231            GetMagickVersion((unsigned long *) NULL));
232          (void) fprintf(stdout,"Copyright: %s\n\n",GetMagickCopyright());
233          return(MagickFalse);
234        }
235    }
236  if (argc < 3)
237    StreamUsage();
238  format="%w,%h,%m";
239  j=1;
240  k=0;
241  NewImageStack();
242  option=(char *) NULL;
243  pend=MagickFalse;
244  stream_info=AcquireStreamInfo(image_info);
245  status=MagickTrue;
246  /*
247    Stream an image.
248  */
249  ReadCommandlLine(argc,&argv);
250  status=ExpandFilenames(&argc,&argv);
251  if (status == MagickFalse)
252    ThrowStreamException(ResourceLimitError,"MemoryAllocationFailed",
253      strerror(errno));
254  status=OpenStream(image_info,stream_info,argv[argc-1],exception);
255  if (status == MagickFalse)
256    {
257      DestroyStream();
258      return(MagickFalse);
259    }
260  for (i=1; i < (long) (argc-1); i++)
261  {
262    option=argv[i];
263    if (LocaleCompare(option,"(") == 0)
264      {
265        FireImageStack(MagickFalse,MagickTrue,pend);
266        if (k == MaxImageStackDepth)
267          ThrowStreamException(OptionError,"ParenthesisNestedTooDeeply",option);
268        PushImageStack();
269        continue;
270      }
271    if (LocaleCompare(option,")") == 0)
272      {
273        FireImageStack(MagickFalse,MagickTrue,MagickTrue);
274        if (k == 0)
275          ThrowStreamException(OptionError,"UnableToParseExpression",option);
276        PopImageStack();
277        continue;
278      }
279    if (IsMagickOption(option) == MagickFalse)
280      {
281        Image
282          *images;
283
284        /*
285          Stream input image.
286        */
287        FireImageStack(MagickFalse,MagickTrue,pend);
288        filename=argv[i];
289        if ((LocaleCompare(filename,"--") == 0) && (i < (argc-1)))
290          filename=argv[++i];
291        (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
292        images=StreamImage(image_info,stream_info,exception);
293        status&=(images != (Image *) NULL) &&
294          (exception->severity < ErrorException);
295        if (images == (Image *) NULL)
296          continue;
297        AppendImageStack(images);
298        continue;
299      }
300    pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
301    switch (*(option+1))
302    {
303      case 'a':
304      {
305        if (LocaleCompare("authenticate",option+1) == 0)
306          {
307            if (*option == '+')
308              break;
309            i++;
310            if (i == (long) (argc-1))
311              ThrowStreamException(OptionError,"MissingArgument",option);
312            break;
313          }
314        ThrowStreamException(OptionError,"UnrecognizedOption",option)
315      }
316      case 'c':
317      {
318        if (LocaleCompare("cache",option+1) == 0)
319          {
320            if (*option == '+')
321              break;
322            i++;
323            if (i == (long) argc)
324              ThrowStreamException(OptionError,"MissingArgument",option);
325            if (IsGeometry(argv[i]) == MagickFalse)
326              ThrowStreamInvalidArgumentException(option,argv[i]);
327            break;
328          }
329        if (LocaleCompare("channel",option+1) == 0)
330          {
331            long
332              channel;
333
334            if (*option == '+')
335              break;
336            i++;
337            if (i == (long) (argc-1))
338              ThrowStreamException(OptionError,"MissingArgument",option);
339            channel=ParseChannelOption(argv[i]);
340            if (channel < 0)
341              ThrowStreamException(OptionError,"UnrecognizedChannelType",
342                argv[i]);
343            break;
344          }
345        if (LocaleCompare("colorspace",option+1) == 0)
346          {
347            long
348              colorspace;
349
350            if (*option == '+')
351              break;
352            i++;
353            if (i == (long) (argc-1))
354              ThrowStreamException(OptionError,"MissingArgument",option);
355            colorspace=ParseMagickOption(MagickColorspaceOptions,MagickFalse,
356              argv[i]);
357            if (colorspace < 0)
358              ThrowStreamException(OptionError,"UnrecognizedColorspace",
359                argv[i]);
360            break;
361          }
362        if (LocaleCompare("compress",option+1) == 0)
363          {
364            long
365              compress;
366
367            if (*option == '+')
368              break;
369            i++;
370            if (i == (long) (argc-1))
371              ThrowStreamException(OptionError,"MissingArgument",option);
372            compress=ParseMagickOption(MagickCompressOptions,MagickFalse,
373              argv[i]);
374            if (compress < 0)
375              ThrowStreamException(OptionError,"UnrecognizedImageCompression",
376                argv[i]);
377            break;
378          }
379        ThrowStreamException(OptionError,"UnrecognizedOption",option)
380      }
381      case 'd':
382      {
383        if (LocaleCompare("debug",option+1) == 0)
384          {
385            long
386              event;
387
388            if (*option == '+')
389              break;
390            i++;
391            if (i == (long) argc)
392              ThrowStreamException(OptionError,"MissingArgument",option);
393            event=ParseMagickOption(MagickLogEventOptions,MagickFalse,argv[i]);
394            if (event < 0)
395              ThrowStreamException(OptionError,"UnrecognizedEventType",argv[i]);
396            (void) SetLogEventMask(argv[i]);
397            break;
398            break;
399          }
400        if (LocaleCompare("define",option+1) == 0)
401          {
402            i++;
403            if (i == (long) argc)
404              ThrowStreamException(OptionError,"MissingArgument",option);
405            if (*option == '+')
406              {
407                const char
408                  *define;
409
410                define=GetImageOption(image_info,argv[i]);
411                if (define == (const char *) NULL)
412                  ThrowStreamException(OptionError,"NoSuchOption",argv[i]);
413                break;
414              }
415            break;
416          }
417        if (LocaleCompare("density",option+1) == 0)
418          {
419            if (*option == '+')
420              break;
421            i++;
422            if (i == (long) argc)
423              ThrowStreamException(OptionError,"MissingArgument",option);
424            if (IsGeometry(argv[i]) == MagickFalse)
425              ThrowStreamInvalidArgumentException(option,argv[i]);
426            break;
427          }
428        if (LocaleCompare("depth",option+1) == 0)
429          {
430            if (*option == '+')
431              break;
432            i++;
433            if (i == (long) argc)
434              ThrowStreamException(OptionError,"MissingArgument",option);
435            if (IsGeometry(argv[i]) == MagickFalse)
436              ThrowStreamInvalidArgumentException(option,argv[i]);
437            break;
438          }
439        ThrowStreamException(OptionError,"UnrecognizedOption",option)
440      }
441      case 'e':
442      {
443        if (LocaleCompare("extract",option+1) == 0)
444          {
445            if (*option == '+')
446              break;
447            i++;
448            if (i == (long) (argc-1))
449              ThrowStreamException(OptionError,"MissingArgument",option);
450            if (IsGeometry(argv[i]) == MagickFalse)
451              ThrowStreamInvalidArgumentException(option,argv[i]);
452            break;
453          }
454        ThrowStreamException(OptionError,"UnrecognizedOption",option)
455      }
456      case 'h':
457      {
458        if ((LocaleCompare("help",option+1) == 0) ||
459            (LocaleCompare("-help",option+1) == 0))
460          StreamUsage();
461        ThrowStreamException(OptionError,"UnrecognizedOption",option)
462      }
463      case 'i':
464      {
465        if (LocaleCompare("identify",option+1) == 0)
466          break;
467        if (LocaleCompare("interlace",option+1) == 0)
468          {
469            long
470              interlace;
471
472            if (*option == '+')
473              break;
474            i++;
475            if (i == (long) argc)
476              ThrowStreamException(OptionError,"MissingArgument",option);
477            interlace=ParseMagickOption(MagickInterlaceOptions,MagickFalse,
478              argv[i]);
479            if (interlace < 0)
480              ThrowStreamException(OptionError,"UnrecognizedInterlaceType",
481                argv[i]);
482            break;
483          }
484        if (LocaleCompare("interpolate",option+1) == 0)
485          {
486            long
487              interpolate;
488
489            if (*option == '+')
490              break;
491            i++;
492            if (i == (long) argc)
493              ThrowStreamException(OptionError,"MissingArgument",option);
494            interpolate=ParseMagickOption(MagickInterpolateOptions,MagickFalse,
495              argv[i]);
496            if (interpolate < 0)
497              ThrowStreamException(OptionError,"UnrecognizedInterpolateMethod",
498                argv[i]);
499            break;
500          }
501        ThrowStreamException(OptionError,"UnrecognizedOption",option)
502      }
503      case 'l':
504      {
505        if (LocaleCompare("limit",option+1) == 0)
506          {
507            char
508              *p;
509
510            long
511              resource;
512
513            if (*option == '+')
514              break;
515            i++;
516            if (i == (long) argc)
517              ThrowStreamException(OptionError,"MissingArgument",option);
518            resource=ParseMagickOption(MagickResourceOptions,MagickFalse,
519              argv[i]);
520            if (resource < 0)
521              ThrowStreamException(OptionError,"UnrecognizedResourceType",
522                argv[i]);
523            i++;
524            if (i == (long) argc)
525              ThrowStreamException(OptionError,"MissingArgument",option);
526            (void) strtod(argv[i],&p);
527            if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
528              ThrowStreamInvalidArgumentException(option,argv[i]);
529            break;
530          }
531        if (LocaleCompare("log",option+1) == 0)
532          {
533            if (*option == '+')
534              break;
535            i++;
536            if ((i == (long) argc) || (strchr(argv[i],'%') == (char *) NULL))
537              ThrowStreamException(OptionError,"MissingArgument",option);
538            break;
539          }
540        ThrowStreamException(OptionError,"UnrecognizedOption",option)
541      }
542      case 'm':
543      {
544        if (LocaleCompare("map",option+1) == 0)
545          {
546            (void) CopyMagickString(argv[i]+1,"san",MaxTextExtent);
547            if (*option == '+')
548              break;
549            i++;
550            SetStreamInfoMap(stream_info,argv[i]);
551            break;
552          }
553        if (LocaleCompare("monitor",option+1) == 0)
554          break;
555        ThrowStreamException(OptionError,"UnrecognizedOption",option)
556      }
557      case 'q':
558      {
559        if (LocaleCompare("quantize",option+1) == 0)
560          {
561            long
562              colorspace;
563
564            if (*option == '+')
565              break;
566            i++;
567            if (i == (long) (argc-1))
568              ThrowStreamException(OptionError,"MissingArgument",option);
569            colorspace=ParseMagickOption(MagickColorspaceOptions,
570              MagickFalse,argv[i]);
571            if (colorspace < 0)
572              ThrowStreamException(OptionError,"UnrecognizedColorspace",
573                argv[i]);
574            break;
575          }
576        if (LocaleCompare("quiet",option+1) == 0)
577          break;
578        ThrowStreamException(OptionError,"UnrecognizedOption",option)
579      }
580      case 'r':
581      {
582        if (LocaleCompare("regard-warnings",option+1) == 0)
583          break;
584        if (LocaleCompare("respect-parenthesis",option+1) == 0)
585          {
586            respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
587            break;
588          }
589        ThrowStreamException(OptionError,"UnrecognizedOption",option)
590      }
591      case 's':
592      {
593        if (LocaleCompare("sampling-factor",option+1) == 0)
594          {
595            if (*option == '+')
596              break;
597            i++;
598            if (i == (long) argc)
599              ThrowStreamException(OptionError,"MissingArgument",option);
600            if (IsGeometry(argv[i]) == MagickFalse)
601              ThrowStreamInvalidArgumentException(option,argv[i]);
602            break;
603          }
604        if (LocaleCompare("seed",option+1) == 0)
605          {
606            if (*option == '+')
607              break;
608            i++;
609            if (i == (long) (argc-1))
610              ThrowStreamException(OptionError,"MissingArgument",option);
611            if (IsGeometry(argv[i]) == MagickFalse)
612              ThrowStreamInvalidArgumentException(option,argv[i]);
613            break;
614          }
615        if (LocaleCompare("set",option+1) == 0)
616          {
617            i++;
618            if (i == (long) argc)
619              ThrowStreamException(OptionError,"MissingArgument",option);
620            if (*option == '+')
621              break;
622            i++;
623            if (i == (long) argc)
624              ThrowStreamException(OptionError,"MissingArgument",option);
625            break;
626          }
627        if (LocaleCompare("size",option+1) == 0)
628          {
629            if (*option == '+')
630              break;
631            i++;
632            if (i == (long) argc)
633              ThrowStreamException(OptionError,"MissingArgument",option);
634            if (IsGeometry(argv[i]) == MagickFalse)
635              ThrowStreamInvalidArgumentException(option,argv[i]);
636            break;
637          }
638        if (LocaleCompare("storage-type",option+1) == 0)
639          {
640            long
641              type;
642
643            if (*option == '+')
644              break;
645            i++;
646            if (i == (long) (argc-1))
647              ThrowStreamException(OptionError,"MissingArgument",option);
648            type=ParseMagickOption(MagickStorageOptions,MagickFalse,argv[i]);
649            if (type < 0)
650              ThrowStreamException(OptionError,"UnrecognizedStorageType",
651                argv[i]);
652            SetStreamInfoStorageType(stream_info,(StorageType) type);
653            break;
654          }
655        ThrowStreamException(OptionError,"UnrecognizedOption",option)
656      }
657      case 't':
658      {
659        if (LocaleCompare("transparent-color",option+1) == 0)
660          {
661            if (*option == '+')
662              break;
663            i++;
664            if (i == (long) (argc-1))
665              ThrowStreamException(OptionError,"MissingArgument",option);
666            break;
667          }
668        ThrowStreamException(OptionError,"UnrecognizedOption",option)
669      }
670      case 'v':
671      {
672        if (LocaleCompare("verbose",option+1) == 0)
673          break;
674        if ((LocaleCompare("version",option+1) == 0) ||
675            (LocaleCompare("-version",option+1) == 0))
676          {
677            (void) fprintf(stdout,"Version: %s\n",
678              GetMagickVersion((unsigned long *) NULL));
679            (void) fprintf(stdout,"Copyright: %s\n\n",GetMagickCopyright());
680            break;
681          }
682        if (LocaleCompare("virtual-pixel",option+1) == 0)
683          {
684            long
685              method;
686
687            if (*option == '+')
688              break;
689            i++;
690            if (i == (long) (argc-1))
691              ThrowStreamException(OptionError,"MissingArgument",option);
692            method=ParseMagickOption(MagickVirtualPixelOptions,MagickFalse,
693              argv[i]);
694            if (method < 0)
695              ThrowStreamException(OptionError,
696                "UnrecognizedVirtualPixelMethod",argv[i]);
697            break;
698          }
699        ThrowStreamException(OptionError,"UnrecognizedOption",option)
700      }
701      case '?':
702        break;
703      default:
704        ThrowStreamException(OptionError,"UnrecognizedOption",option)
705    }
706    fire=ParseMagickOption(MagickImageListOptions,MagickFalse,option+1) < 0 ?
707      MagickFalse : MagickTrue;
708    if (fire != MagickFalse)
709      FireImageStack(MagickFalse,MagickTrue,MagickTrue);
710  }
711  if (k != 0)
712    ThrowStreamException(OptionError,"UnbalancedParenthesis",argv[i]);
713  if (i-- != (long) (argc-1))
714    ThrowStreamException(OptionError,"MissingAnImageFilename",argv[i]);
715  if (image == (Image *) NULL)
716    ThrowStreamException(OptionError,"MissingAnImageFilename",argv[i]);
717  FinalizeImageSettings(image_info,image);
718  DestroyStream();
719  return(status != 0 ? MagickTrue : MagickFalse);
720}
Note: See TracBrowser for help on using the browser.