/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S p l i c e I m a g e I n t o L i s t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SpliceImageIntoList() removes 'length' images from the list and replaces % them with the specified splice. Removed images are returned. % % The format of the SpliceImageIntoList method is: % % SpliceImageIntoList(Image **images,const unsigned long, % const Image *splice) % % A description of each parameter follows: % % o images: the image list. % % o length: the length of the image list to remove. % % o splice: Replace the removed image list with this list. % */ MagickExport Image *SpliceImageIntoList(Image **images, const unsigned long length,const Image *splice) { Image *image, *split; register unsigned long i; assert(images != (Image **) NULL); assert(splice != (Image *) NULL); assert(splice->signature == MagickSignature); if ((*images) == (Image *) NULL) return((Image *) NULL); assert((*images)->signature == MagickSignature); if ((*images)->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", (*images)->filename); split=SplitImageList(*images); AppendImageToList(images,splice); image=(Image *) NULL; for (i=0; (i < length) && (split != (Image *) NULL); i++) AppendImageToList(&image,RemoveImageFromList(&split)); AppendImageToList(images,split); return(image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e p a r a t e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SeparateImages() returns a separate grayscale image for each channel % specified. % % The format of the SeparateImages method is: % % Image *SeparateImages(const Image *image,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *SeparateImages(const Image *image,ExceptionInfo *exception) { Image *images, *separate_image; register ssize_t i; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); images=NewImageList(); for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); if ((traits == UndefinedPixelTrait) || ((traits & UpdatePixelTrait) == 0)) continue; separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception); if (separate_image != (Image *) NULL) AppendImageToList(&images,separate_image); } if (images == (Image *) NULL) images=SeparateImage(image,UndefinedChannel,exception); return(images); }
Image *AutoResizeImage(const Image *image,const char *option, MagickOffsetType *count,ExceptionInfo *exception) { #define MAX_SIZES 16 char *q; const char *p; Image *resized, *images; register ssize_t i; size_t sizes[MAX_SIZES]={256,192,128,96,64,48,40,32,24,16}; images=NULL; *count=0; i=0; p=option; while (*p != '\0' && i < MAX_SIZES) { size_t size; while ((isspace((int) ((unsigned char) *p)) != 0)) p++; size=(size_t)strtol(p,&q,10); if ((p == q) || (size < 16) || (size > 256)) return((Image *) NULL); p=q; sizes[i++]=size; while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ',')) p++; } if (i==0) i=10; *count=i; for (i=0; i < *count; i++) { resized=ResizeImage(image,sizes[i],sizes[i],image->filter,exception); if (resized == (Image *) NULL) return(DestroyImageList(images)); if (images == (Image *) NULL) images=resized; else AppendImageToList(&images,resized); } return(images); }
/** * Convert an array of Image *s to an ImageMagick scene sequence (i.e. a * doubly-linked list of Images). * * No Ruby usage (internal function) * * @param imagelist the imagelist * @return a pointer to the head of the scene sequence list * @see rm_imagelist_from_images */ static Image * images_from_imagelist(VALUE imagelist) { long x, len; Image *head = NULL; VALUE images, t; len = check_imagelist_length(imagelist); images = rb_iv_get(imagelist, "@images"); for (x = 0; x < len; x++) { Image *image; t = rb_ary_entry(images, x); image = rm_check_destroyed(t); // avoid a loop in this linked imagelist, issue #202 if (head == image || GetPreviousImageInList(image) != NULL) { image = rm_clone_image(image); } AppendImageToList(&head, image); } RB_GC_GUARD(images); RB_GC_GUARD(t); return head; }
/* Extern: images_from_imagelist Purpose: Convert an array of Image *s to an ImageMagick scene sequence (i.e. a doubly-linked list of Images) Returns: a pointer to the head of the scene sequence list */ static Image * images_from_imagelist(VALUE imagelist) { long x, len; Image *head = NULL; volatile VALUE images, t; len = imagelist_length(imagelist); if (len == 0) { rb_raise(rb_eArgError, "no images in this image list"); } images = rb_iv_get(imagelist, "@images"); for (x = 0; x < len; x++) { Image *image; t = rb_ary_entry(images, x); image = rm_check_destroyed(t); AppendImageToList(&head, image); } return head; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I n s e r t I m a g e I n L i s t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % InsertImageInList() inserts the second image or image list into the first % image list immediatally after the image pointed to. The given image list % pointer is unchanged unless previously empty. % % The format of the InsertImageInList method is: % % InsertImageInList(Image **images,Image *image) % % A description of each parameter follows: % % o images: the image list to insert into. % % o image: the image list to insert. % */ MagickExport void InsertImageInList(Image **images,Image *image) { Image *split; assert(images != (Image **) NULL); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if ((*images) == (Image *) NULL) return; assert((*images)->signature == MagickSignature); split=SplitImageList(*images); AppendImageToList(images,image); AppendImageToList(images,split); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % P i n g I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PingImages() pings one or more images and returns them as an image list. % % The format of the PingImage method is: % % Image *PingImages(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *PingImages(const ImageInfo *image_info, ExceptionInfo *exception) { char filename[MaxTextExtent]; Image *image, *images; ImageInfo *read_info; /* Ping image list from a file. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); (void) InterpretImageFilename(image_info,(Image *) NULL,image_info->filename, (int) image_info->scene,filename,exception); if (LocaleCompare(filename,image_info->filename) != 0) { ExceptionInfo *sans; ssize_t extent, scene; /* Images of the form image-%d.png[1-5]. */ read_info=CloneImageInfo(image_info); sans=AcquireExceptionInfo(); (void) SetImageInfo(read_info,0,sans); sans=DestroyExceptionInfo(sans); (void) CopyMagickString(filename,read_info->filename,MaxTextExtent); images=NewImageList(); extent=(ssize_t) (read_info->scene+read_info->number_scenes); for (scene=(ssize_t) read_info->scene; scene < (ssize_t) extent; scene++) { (void) InterpretImageFilename(image_info,(Image *) NULL,filename,(int) scene,read_info->filename,exception); image=PingImage(read_info,exception); if (image == (Image *) NULL) continue; AppendImageToList(&images,image); } read_info=DestroyImageInfo(read_info); return(images); } return(PingImage(image_info,exception)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e p a r a t e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SeparateImages() returns a separate grayscale image for each channel % specified. % % The format of the SeparateImages method is: % % MagickBooleanType SeparateImages(const Image *image, % const ChannelType channel,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o channel: Identify which channels to extract: RedChannel, GreenChannel, % BlueChannel, OpacityChannel, CyanChannel, MagentaChannel, % YellowChannel, or BlackChannel. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *SeparateImages(const Image *image,const ChannelType channel, ExceptionInfo *exception) { Image *images, *separate_image; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); images=NewImageList(); if ((channel & RedChannel) != 0) { separate_image=CloneImage(image,0,0,MagickTrue,exception); (void) SeparateImageChannel(separate_image,RedChannel); AppendImageToList(&images,separate_image); } if ((channel & GreenChannel) != 0) { separate_image=CloneImage(image,0,0,MagickTrue,exception); (void) SeparateImageChannel(separate_image,GreenChannel); AppendImageToList(&images,separate_image); } if ((channel & BlueChannel) != 0) { separate_image=CloneImage(image,0,0,MagickTrue,exception); (void) SeparateImageChannel(separate_image,BlueChannel); AppendImageToList(&images,separate_image); } if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace)) { separate_image=CloneImage(image,0,0,MagickTrue,exception); (void) SeparateImageChannel(separate_image,BlackChannel); AppendImageToList(&images,separate_image); } if ((channel & AlphaChannel) != 0) { separate_image=CloneImage(image,0,0,MagickTrue,exception); (void) SeparateImageChannel(separate_image,TrueAlphaChannel); AppendImageToList(&images,separate_image); } return(images); }
/** * Clone a list of images, handle errors. * * No Ruby usage (internal function) * * @param images the images * @return a new array of images */ static Image * clone_imagelist(Image *images) { Image *new_imagelist = NULL, *image, *clone; ExceptionInfo *exception; exception = AcquireExceptionInfo(); image = GetFirstImageInList(images); while (image) { clone = CloneImage(image, 0, 0, MagickTrue, exception); rm_check_exception(exception, new_imagelist, DestroyOnError); AppendImageToList(&new_imagelist, clone); image = GetNextImageInList(image); } (void) DestroyExceptionInfo(exception); return new_imagelist; }
/* Extern: images_from_imagelist Purpose: Convert an array of Image *s to an ImageMagick scene sequence (i.e. a doubly-linked list of Images) Returns: a pointer to the head of the scene sequence list */ static Image * images_from_imagelist(VALUE imagelist) { long x, len; Image *head = NULL; volatile VALUE images, t; len = check_imagelist_length(imagelist); images = rb_iv_get(imagelist, "@images"); for (x = 0; x < len; x++) { Image *image; t = rb_ary_entry(images, x); image = rm_check_destroyed(t); AppendImageToList(&head, image); } return head; }
static int load_images(LogoPrivateData *pd) { Image *timg; Image *nimg; pd->images = GetFirstImageInList(pd->magick.image); nimg = NewImageList(); while (pd->images != (Image *)NULL) { if (pd->flip) { timg = FlipImage(pd->images, &pd->magick.exception_info); if (timg == NULL) { CatchException(&pd->magick.exception_info); return TC_ERROR; } AppendImageToList(&nimg, timg); } pd->images = GetNextImageInList(pd->images); pd->nr_of_images++; } // check for memleaks; //DestroyImageList(image); if (pd->flip) { /* DANGEROUS!!! */ pd->magick.image = nimg; } /* for running through image sequence */ /* DANGEROUS!!! */ pd->images = pd->magick.image; return TC_OK; }
MagickExport Image *ForwardFourierTransformImage(const Image *image, const MagickBooleanType modulus,ExceptionInfo *exception) { Image *fourier_image; fourier_image=NewImageList(); #if !defined(MAGICKCORE_FFTW_DELEGATE) (void) modulus; (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (FFTW)", image->filename); #else { Image *magnitude_image; size_t extent, width; width=image->columns; if ((image->columns != image->rows) || ((image->columns % 2) != 0) || ((image->rows % 2) != 0)) { extent=image->columns < image->rows ? image->rows : image->columns; width=(extent & 0x01) == 1 ? extent+1UL : extent; } magnitude_image=CloneImage(image,width,width,MagickFalse,exception); if (magnitude_image != (Image *) NULL) { Image *phase_image; magnitude_image->storage_class=DirectClass; magnitude_image->depth=32UL; phase_image=CloneImage(image,width,width,MagickFalse,exception); if (phase_image == (Image *) NULL) magnitude_image=DestroyImage(magnitude_image); else { MagickBooleanType is_gray, status; phase_image->storage_class=DirectClass; phase_image->depth=32UL; AppendImageToList(&fourier_image,magnitude_image); AppendImageToList(&fourier_image,phase_image); status=MagickTrue; is_gray=IsGrayImage(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel sections #endif { #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp section #endif { MagickBooleanType thread_status; if (is_gray != MagickFalse) thread_status=ForwardFourierTransformChannel(image, GrayChannels,modulus,fourier_image,exception); else thread_status=ForwardFourierTransformChannel(image, RedChannel,modulus,fourier_image,exception); if (thread_status == MagickFalse) status=thread_status; } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp section #endif { MagickBooleanType thread_status; thread_status=MagickTrue; if (is_gray == MagickFalse) thread_status=ForwardFourierTransformChannel(image, GreenChannel,modulus,fourier_image,exception); if (thread_status == MagickFalse) status=thread_status; } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp section #endif { MagickBooleanType thread_status; thread_status=MagickTrue; if (is_gray == MagickFalse) thread_status=ForwardFourierTransformChannel(image, BlueChannel,modulus,fourier_image,exception); if (thread_status == MagickFalse) status=thread_status; } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp section #endif { MagickBooleanType thread_status; thread_status=MagickTrue; if (image->matte != MagickFalse) thread_status=ForwardFourierTransformChannel(image, OpacityChannel,modulus,fourier_image,exception); if (thread_status == MagickFalse) status=thread_status; } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp section #endif { MagickBooleanType thread_status; thread_status=MagickTrue; if (image->colorspace == CMYKColorspace) thread_status=ForwardFourierTransformChannel(image, IndexChannel,modulus,fourier_image,exception); if (thread_status == MagickFalse) status=thread_status; } } if (status == MagickFalse) fourier_image=DestroyImageList(fourier_image); fftw_cleanup(); } } } #endif return(fourier_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d J N X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadJNXImage() reads an image in the Garmin tile storage format and returns % it. It allocates the memory necessary for the new Image structure and % returns a pointer to the new image. % % The format of the ReadJNXImage method is: % % Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define JNXMaxLevels 20 Image *image, *images; JNXInfo jnx_info; JNXLevelInfo jnx_level_info[JNXMaxLevels]; MagickBooleanType status; register ssize_t i; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Read JNX header. */ (void) ResetMagickMemory(&jnx_info,0,sizeof(jnx_info)); jnx_info.version=(int) ReadBlobLSBLong(image); if ((jnx_info.version != 3) && (jnx_info.version != 4)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); jnx_info.serial=(int) ReadBlobLSBLong(image); jnx_info.northeast.x=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; jnx_info.northeast.y=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; jnx_info.southwest.x=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; jnx_info.southwest.y=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; jnx_info.levels=(int) ReadBlobLSBLong(image); if (jnx_info.levels > JNXMaxLevels) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); jnx_info.expire=(int) ReadBlobLSBLong(image); jnx_info.id=(int) ReadBlobLSBLong(image); jnx_info.crc=(int) ReadBlobLSBLong(image); jnx_info.signature=(int) ReadBlobLSBLong(image); jnx_info.offset=ReadBlobLSBLong(image); if (jnx_info.version > 3) jnx_info.order=(int) ReadBlobLSBLong(image); else if (jnx_info.version == 3) jnx_info.order=30; /* Read JNX levels. */ (void) ResetMagickMemory(&jnx_level_info,0,sizeof(jnx_level_info)); for (i=0; i < (ssize_t) jnx_info.levels; i++) { jnx_level_info[i].count=(int) ReadBlobLSBLong(image); if (jnx_level_info[i].count > 50000) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); jnx_level_info[i].offset=(int) ReadBlobLSBLong(image); jnx_level_info[i].scale=ReadBlobLSBLong(image); if (jnx_info.version > 3) { register ssize_t j; unsigned short c; (void) ReadBlobLSBLong(image); j=0; while ((c=ReadBlobLSBShort(image)) != 0) if (j < (MagickPathExtent-1)) jnx_level_info[i].copyright[j++]=c; jnx_level_info[i].copyright[j]=0; } } /* Read JNX tiles. */ images=NewImageList(); for (i=0; i < (ssize_t) jnx_info.levels; i++) { MagickOffsetType offset; register ssize_t j; offset=SeekBlob(image,(MagickOffsetType) jnx_level_info[i].offset,SEEK_SET); if (offset != (MagickOffsetType) jnx_level_info[i].offset) continue; for (j=0; j < (ssize_t) jnx_level_info[i].count; j++) { Image *tile_image; ImageInfo *read_info; int tile_offset; MagickOffsetType restore_offset; PointInfo northeast, southwest; ssize_t count; unsigned char *blob; unsigned int tile_length; northeast.x=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; northeast.y=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; southwest.x=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; southwest.y=180.0*((int) ReadBlobLSBLong(image))/0x7fffffff; (void) ReadBlobLSBShort(image); /* width */ (void) ReadBlobLSBShort(image); /* height */ tile_length=ReadBlobLSBLong(image); tile_offset=(int) ReadBlobLSBLong(image); if (tile_offset == -1) continue; restore_offset=TellBlob(image); if (restore_offset < 0) continue; offset=SeekBlob(image,(MagickOffsetType) tile_offset,SEEK_SET); if (offset != (MagickOffsetType) tile_offset) continue; /* Read a tile. */ blob=(unsigned char *) AcquireQuantumMemory((size_t) tile_length+2, sizeof(*blob)); if (blob == (unsigned char *) NULL) { if (images != (Image *) NULL) images=DestroyImageList(images); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } blob[0]=0xFF; blob[1]=0xD8; count=ReadBlob(image,tile_length,blob+2); if (count != (ssize_t) tile_length) { if (images != (Image *) NULL) images=DestroyImageList(images); blob=(unsigned char *) RelinquishMagickMemory(blob); ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); } read_info=CloneImageInfo(image_info); (void) CopyMagickString(read_info->magick,"JPEG",MagickPathExtent); tile_image=BlobToImage(read_info,blob,tile_length+2,exception); read_info=DestroyImageInfo(read_info); blob=(unsigned char *) RelinquishMagickMemory(blob); offset=SeekBlob(image,restore_offset,SEEK_SET); if (tile_image == (Image *) NULL) continue; (void) CopyMagickString(tile_image->magick,image->magick,MagickPathExtent); (void) FormatImageProperty(tile_image,"jnx:northeast","%.20g,%.20g", northeast.x,northeast.y); (void) FormatImageProperty(tile_image,"jnx:southwest","%.20g,%.20g", southwest.x,southwest.y); AppendImageToList(&images,tile_image); } if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) i, (MagickSizeType) jnx_info.levels); if (proceed == MagickFalse) status=MagickFalse; } } (void) CloseBlob(image); image=DestroyImage(image); if (images == (Image *) NULL) return((Image *) NULL); return(GetFirstImageInList(images)); }
WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info, int argc,char **argv,char **metadata,ExceptionInfo *exception) { #define DefaultDissimilarityThreshold 0.31830988618379067154 #define DestroyCompare() \ { \ if (similarity_image != (Image *) NULL) \ similarity_image=DestroyImageList(similarity_image); \ if (difference_image != (Image *) NULL) \ difference_image=DestroyImageList(difference_image); \ DestroyImageStack(); \ for (i=0; i < (ssize_t) argc; i++) \ argv[i]=DestroyString(argv[i]); \ argv=(char **) RelinquishMagickMemory(argv); \ } #define ThrowCompareException(asperity,tag,option) \ { \ if (exception->severity < (asperity)) \ (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \ "`%s'",option); \ DestroyCompare(); \ return(MagickFalse); \ } #define ThrowCompareInvalidArgumentException(option,argument) \ { \ (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \ "InvalidArgument","`%s': %s",option,argument); \ DestroyCompare(); \ return(MagickFalse); \ } char *filename, *option; const char *format; ChannelType channels; double dissimilarity_threshold, distortion, similarity_metric; Image *difference_image, *image, *reconstruct_image, *similarity_image; ImageStack image_stack[MaxImageStackDepth+1]; MagickBooleanType fire, pend, respect_parenthesis, subimage_search; MagickStatusType status; MetricType metric; RectangleInfo offset; register ssize_t i; ssize_t j, k; /* Set defaults. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(exception != (ExceptionInfo *) NULL); if (argc == 2) { option=argv[1]; if ((LocaleCompare("version",option+1) == 0) || (LocaleCompare("-version",option+1) == 0)) { (void) FormatLocaleFile(stdout,"Version: %s\n", GetMagickVersion((size_t *) NULL)); (void) FormatLocaleFile(stdout,"Copyright: %s\n", GetMagickCopyright()); (void) FormatLocaleFile(stdout,"Features: %s\n\n", GetMagickFeatures()); return(MagickFalse); } } if (argc < 3) return(CompareUsage()); channels=CompositeChannels; difference_image=NewImageList(); similarity_image=NewImageList(); dissimilarity_threshold=DefaultDissimilarityThreshold; distortion=0.0; format=(char *) NULL; j=1; k=0; metric=UndefinedMetric; NewImageStack(); option=(char *) NULL; pend=MagickFalse; reconstruct_image=NewImageList(); respect_parenthesis=MagickFalse; status=MagickTrue; subimage_search=MagickFalse; /* Compare an image. */ ReadCommandlLine(argc,&argv); status=ExpandFilenames(&argc,&argv); if (status == MagickFalse) ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed", GetExceptionMessage(errno)); for (i=1; i < (ssize_t) (argc-1); i++) { option=argv[i]; if (LocaleCompare(option,"(") == 0) { FireImageStack(MagickTrue,MagickTrue,pend); if (k == MaxImageStackDepth) ThrowCompareException(OptionError,"ParenthesisNestedTooDeeply", option); PushImageStack(); continue; } if (LocaleCompare(option,")") == 0) { FireImageStack(MagickTrue,MagickTrue,MagickTrue); if (k == 0) ThrowCompareException(OptionError,"UnableToParseExpression",option); PopImageStack(); continue; } if (IsCommandOption(option) == MagickFalse) { Image *images; /* Read input image. */ FireImageStack(MagickFalse,MagickFalse,pend); filename=argv[i]; if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1))) filename=argv[++i]; (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); images=ReadImages(image_info,exception); status&=(images != (Image *) NULL) && (exception->severity < ErrorException); if (images == (Image *) NULL) continue; AppendImageStack(images); continue; } pend=image != (Image *) NULL ? MagickTrue : MagickFalse; switch (*(option+1)) { case 'a': { if (LocaleCompare("alpha",option+1) == 0) { ssize_t type; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); type=ParseCommandOption(MagickAlphaOptions,MagickFalse,argv[i]); if (type < 0) ThrowCompareException(OptionError,"UnrecognizedAlphaChannelType", argv[i]); break; } if (LocaleCompare("authenticate",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option); } case 'c': { if (LocaleCompare("cache",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("channel",option+1) == 0) { ssize_t channel; if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); channel=ParseChannelOption(argv[i]); if (channel < 0) ThrowCompareException(OptionError,"UnrecognizedChannelType", argv[i]); channels=(ChannelType) channel; break; } if (LocaleCompare("colorspace",option+1) == 0) { ssize_t colorspace; if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); colorspace=ParseCommandOption(MagickColorspaceOptions,MagickFalse, argv[i]); if (colorspace < 0) ThrowCompareException(OptionError,"UnrecognizedColorspace", argv[i]); break; } if (LocaleCompare("compose",option+1) == 0) { ssize_t compose; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); compose=ParseCommandOption(MagickComposeOptions,MagickFalse, argv[i]); if (compose < 0) ThrowCompareException(OptionError,"UnrecognizedComposeOperator", argv[i]); break; } if (LocaleCompare("compress",option+1) == 0) { ssize_t compress; if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); compress=ParseCommandOption(MagickCompressOptions,MagickFalse, argv[i]); if (compress < 0) ThrowCompareException(OptionError,"UnrecognizedImageCompression", argv[i]); break; } if (LocaleCompare("concurrent",option+1) == 0) break; ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'd': { if (LocaleCompare("debug",option+1) == 0) { LogEventType event_mask; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); event_mask=SetLogEventMask(argv[i]); if (event_mask == UndefinedEvents) ThrowCompareException(OptionError,"UnrecognizedEventType", argv[i]); break; } if (LocaleCompare("decipher",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("define",option+1) == 0) { i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (*option == '+') { const char *define; define=GetImageOption(image_info,argv[i]); if (define == (const char *) NULL) ThrowCompareException(OptionError,"NoSuchOption",argv[i]); break; } break; } if (LocaleCompare("density",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("depth",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("dissimilarity-threshold",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); if (*option == '+') dissimilarity_threshold=DefaultDissimilarityThreshold; else dissimilarity_threshold=StringToDouble(argv[i],(char **) NULL); break; } if (LocaleCompare("duration",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'e': { if (LocaleCompare("encipher",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("extract",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'f': { if (LocaleCompare("format",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); format=argv[i]; break; } if (LocaleCompare("fuzz",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'h': { if ((LocaleCompare("help",option+1) == 0) || (LocaleCompare("-help",option+1) == 0)) return(CompareUsage()); if (LocaleCompare("highlight-color",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'i': { if (LocaleCompare("identify",option+1) == 0) break; if (LocaleCompare("interlace",option+1) == 0) { ssize_t interlace; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse, argv[i]); if (interlace < 0) ThrowCompareException(OptionError,"UnrecognizedInterlaceType", argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'l': { if (LocaleCompare("limit",option+1) == 0) { char *p; double value; ssize_t resource; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); resource=ParseCommandOption(MagickResourceOptions,MagickFalse, argv[i]); if (resource < 0) ThrowCompareException(OptionError,"UnrecognizedResourceType", argv[i]); i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); value=StringToDouble(argv[i],&p); (void) value; if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0)) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("list",option+1) == 0) { ssize_t list; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]); if (list < 0) ThrowCompareException(OptionError,"UnrecognizedListType",argv[i]); status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **) argv+j,exception); DestroyCompare(); return(status != 0 ? MagickFalse : MagickTrue); } if (LocaleCompare("log",option+1) == 0) { if (*option == '+') break; i++; if ((i == (ssize_t) argc) || (strchr(argv[i],'%') == (char *) NULL)) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("lowlight-color",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'm': { if (LocaleCompare("matte",option+1) == 0) break; if (LocaleCompare("metric",option+1) == 0) { ssize_t type; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); type=ParseCommandOption(MagickMetricOptions,MagickTrue,argv[i]); if (type < 0) ThrowCompareException(OptionError,"UnrecognizedMetricType", argv[i]); metric=(MetricType) type; break; } if (LocaleCompare("monitor",option+1) == 0) break; ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'p': { if (LocaleCompare("passphrase",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("profile",option+1) == 0) { i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'q': { if (LocaleCompare("quality",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("quantize",option+1) == 0) { ssize_t colorspace; if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); colorspace=ParseCommandOption(MagickColorspaceOptions, MagickFalse,argv[i]); if (colorspace < 0) ThrowCompareException(OptionError,"UnrecognizedColorspace", argv[i]); break; } if (LocaleCompare("quiet",option+1) == 0) break; ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'r': { if (LocaleCompare("regard-warnings",option+1) == 0) break; if (LocaleNCompare("respect-parentheses",option+1,17) == 0) { respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse; break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 's': { if (LocaleCompare("sampling-factor",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("seed",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("set",option+1) == 0) { i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("size",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowCompareInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("subimage-search",option+1) == 0) { if (*option == '+') { subimage_search=MagickFalse; break; } subimage_search=MagickTrue; break; } if (LocaleCompare("synchronize",option+1) == 0) break; ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 't': { if (LocaleCompare("taint",option+1) == 0) break; if (LocaleCompare("transparent-color",option+1) == 0) { if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("type",option+1) == 0) { ssize_t type; if (*option == '+') break; i++; if (i == (ssize_t) argc) ThrowCompareException(OptionError,"MissingArgument",option); type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]); if (type < 0) ThrowCompareException(OptionError,"UnrecognizedImageType", argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case 'v': { if (LocaleCompare("verbose",option+1) == 0) break; if ((LocaleCompare("version",option+1) == 0) || (LocaleCompare("-version",option+1) == 0)) { (void) FormatLocaleFile(stdout,"Version: %s\n", GetMagickVersion((size_t *) NULL)); (void) FormatLocaleFile(stdout,"Copyright: %s\n", GetMagickCopyright()); (void) FormatLocaleFile(stdout,"Features: %s\n\n", GetMagickFeatures()); break; } if (LocaleCompare("virtual-pixel",option+1) == 0) { ssize_t method; if (*option == '+') break; i++; if (i == (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingArgument",option); method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse, argv[i]); if (method < 0) ThrowCompareException(OptionError, "UnrecognizedVirtualPixelMethod",argv[i]); break; } ThrowCompareException(OptionError,"UnrecognizedOption",option) } case '?': break; default: ThrowCompareException(OptionError,"UnrecognizedOption",option) } fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) & FireOptionFlag) == 0 ? MagickFalse : MagickTrue; if (fire != MagickFalse) FireImageStack(MagickTrue,MagickTrue,MagickTrue); } if (k != 0) ThrowCompareException(OptionError,"UnbalancedParenthesis",argv[i]); if (i-- != (ssize_t) (argc-1)) ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]); if ((image == (Image *) NULL) || (GetImageListLength(image) < 2)) ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]); FinalizeImageSettings(image_info,image,MagickTrue); if ((image == (Image *) NULL) || (GetImageListLength(image) < 2)) ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]); image=GetImageFromList(image,0); reconstruct_image=GetImageFromList(image,1); if (subimage_search != MagickFalse) { similarity_image=SimilarityMetricImage(image,reconstruct_image,metric, &offset,&similarity_metric,exception); if (similarity_metric > dissimilarity_threshold) ThrowCompareException(ImageError,"ImagesTooDissimilar",image->filename); } if ((reconstruct_image->columns == image->columns) && (reconstruct_image->rows == image->rows)) difference_image=CompareImageChannels(image,reconstruct_image,channels, metric,&distortion,exception); else if (similarity_image == (Image *) NULL) ThrowCompareException(OptionError,"ImageWidthsOrHeightsDiffer", image->filename) else { Image *composite_image; /* Determine if reconstructed image is a subimage of the image. */ composite_image=CloneImage(image,0,0,MagickTrue,exception); if (composite_image == (Image *) NULL) difference_image=CompareImageChannels(image,reconstruct_image, channels,metric,&distortion,exception); else { (void) CompositeImage(composite_image,CopyCompositeOp, reconstruct_image,offset.x,offset.y); difference_image=CompareImageChannels(image,composite_image, channels,metric,&distortion,exception); if (difference_image != (Image *) NULL) { difference_image->page.x=offset.x; difference_image->page.y=offset.y; } composite_image=DestroyImage(composite_image); } if (difference_image != (Image *) NULL) { AppendImageToList(&difference_image,similarity_image); similarity_image=(Image *) NULL; } } if (difference_image == (Image *) NULL) status=0; else { if (image_info->verbose != MagickFalse) (void) IsImagesEqual(image,reconstruct_image); if (*difference_image->magick == '\0') (void) CopyMagickString(difference_image->magick,image->magick, MaxTextExtent); if (image_info->verbose == MagickFalse) { switch (metric) { case FuzzErrorMetric: case MeanAbsoluteErrorMetric: case MeanSquaredErrorMetric: case RootMeanSquaredErrorMetric: case PeakAbsoluteErrorMetric: { (void) FormatLocaleFile(stderr,"%g (%g)",QuantumRange*distortion, (double) distortion); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) (void) FormatLocaleFile(stderr," @ %.20g,%.20g",(double) difference_image->page.x,(double) difference_image->page.y); (void) FormatLocaleFile(stderr,"\n"); break; } case AbsoluteErrorMetric: case NormalizedCrossCorrelationErrorMetric: case PeakSignalToNoiseRatioMetric: { (void) FormatLocaleFile(stderr,"%g",distortion); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) (void) FormatLocaleFile(stderr," @ %.20g,%.20g",(double) difference_image->page.x,(double) difference_image->page.y); (void) FormatLocaleFile(stderr,"\n"); break; } case MeanErrorPerPixelMetric: { (void) FormatLocaleFile(stderr,"%g (%g, %g)",distortion, image->error.normalized_mean_error, image->error.normalized_maximum_error); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) (void) FormatLocaleFile(stderr," @ %.20g,%.20g",(double) difference_image->page.x,(double) difference_image->page.y); (void) FormatLocaleFile(stderr,"\n"); break; } case UndefinedMetric: break; } } else { double *channel_distortion; channel_distortion=GetImageChannelDistortions(image,reconstruct_image, metric,&image->exception); (void) FormatLocaleFile(stderr,"Image: %s\n",image->filename); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) (void) FormatLocaleFile(stderr,"Offset: %.20g,%.20g\n",(double) difference_image->page.x,(double) difference_image->page.y); (void) FormatLocaleFile(stderr," Channel distortion: %s\n", CommandOptionToMnemonic(MagickMetricOptions,(ssize_t) metric)); switch (metric) { case FuzzErrorMetric: case MeanAbsoluteErrorMetric: case MeanSquaredErrorMetric: case RootMeanSquaredErrorMetric: case PeakAbsoluteErrorMetric: { switch (image->colorspace) { case RGBColorspace: default: { (void) FormatLocaleFile(stderr," red: %g (%g)\n", QuantumRange*channel_distortion[RedChannel], channel_distortion[RedChannel]); (void) FormatLocaleFile(stderr," green: %g (%g)\n", QuantumRange*channel_distortion[GreenChannel], channel_distortion[GreenChannel]); (void) FormatLocaleFile(stderr," blue: %g (%g)\n", QuantumRange*channel_distortion[BlueChannel], channel_distortion[BlueChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g (%g)\n", QuantumRange*channel_distortion[OpacityChannel], channel_distortion[OpacityChannel]); break; } case CMYKColorspace: { (void) FormatLocaleFile(stderr," cyan: %g (%g)\n", QuantumRange*channel_distortion[CyanChannel], channel_distortion[CyanChannel]); (void) FormatLocaleFile(stderr," magenta: %g (%g)\n", QuantumRange*channel_distortion[MagentaChannel], channel_distortion[MagentaChannel]); (void) FormatLocaleFile(stderr," yellow: %g (%g)\n", QuantumRange*channel_distortion[YellowChannel], channel_distortion[YellowChannel]); (void) FormatLocaleFile(stderr," black: %g (%g)\n", QuantumRange*channel_distortion[BlackChannel], channel_distortion[BlackChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g (%g)\n", QuantumRange*channel_distortion[OpacityChannel], channel_distortion[OpacityChannel]); break; } case GRAYColorspace: { (void) FormatLocaleFile(stderr," gray: %g (%g)\n", QuantumRange*channel_distortion[GrayChannel], channel_distortion[GrayChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g (%g)\n", QuantumRange*channel_distortion[OpacityChannel], channel_distortion[OpacityChannel]); break; } } (void) FormatLocaleFile(stderr," all: %g (%g)\n", QuantumRange*channel_distortion[CompositeChannels], channel_distortion[CompositeChannels]); break; } case AbsoluteErrorMetric: case NormalizedCrossCorrelationErrorMetric: case PeakSignalToNoiseRatioMetric: { switch (image->colorspace) { case RGBColorspace: default: { (void) FormatLocaleFile(stderr," red: %g\n", channel_distortion[RedChannel]); (void) FormatLocaleFile(stderr," green: %g\n", channel_distortion[GreenChannel]); (void) FormatLocaleFile(stderr," blue: %g\n", channel_distortion[BlueChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g\n", channel_distortion[OpacityChannel]); break; } case CMYKColorspace: { (void) FormatLocaleFile(stderr," cyan: %g\n", channel_distortion[CyanChannel]); (void) FormatLocaleFile(stderr," magenta: %g\n", channel_distortion[MagentaChannel]); (void) FormatLocaleFile(stderr," yellow: %g\n", channel_distortion[YellowChannel]); (void) FormatLocaleFile(stderr," black: %g\n", channel_distortion[BlackChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g\n", channel_distortion[OpacityChannel]); break; } case GRAYColorspace: { (void) FormatLocaleFile(stderr," gray: %g\n", channel_distortion[GrayChannel]); if (image->matte != MagickFalse) (void) FormatLocaleFile(stderr," alpha: %g\n", channel_distortion[OpacityChannel]); break; } } (void) FormatLocaleFile(stderr," all: %g\n", channel_distortion[CompositeChannels]); break; } case MeanErrorPerPixelMetric: { (void) FormatLocaleFile(stderr," %g (%g, %g)\n", channel_distortion[CompositeChannels], image->error.normalized_mean_error, image->error.normalized_maximum_error); break; } case UndefinedMetric: break; } channel_distortion=(double *) RelinquishMagickMemory( channel_distortion); } status&=WriteImages(image_info,difference_image,argv[argc-1],exception); if ((metadata != (char **) NULL) && (format != (char *) NULL)) { char *text; text=InterpretImageProperties(image_info,difference_image,format); if (text == (char *) NULL) ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed", GetExceptionMessage(errno)); (void) ConcatenateString(&(*metadata),text); (void) ConcatenateString(&(*metadata),"\n"); text=DestroyString(text); } difference_image=DestroyImageList(difference_image); } DestroyCompare(); return(status != 0 ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d S C R E E N S H O T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadSCREENSHOTImage() Takes a screenshot from the monitor(s). % % The format of the ReadSCREENSHOTImage method is: % % Image *ReadXImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadSCREENSHOTImage(const ImageInfo *image_info, ExceptionInfo *exception) { Image *image; assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=(Image *) NULL; #if defined(MAGICKCORE_WINGDI32_DELEGATE) { BITMAPINFO bmi; DISPLAY_DEVICE device; HBITMAP bitmap, bitmapOld; HDC bitmapDC, hDC; Image *screen; int i; MagickBooleanType status; register PixelPacket *q; register ssize_t x; RGBTRIPLE *p; ssize_t y; assert(image_info != (const ImageInfo *) NULL); i=0; device.cb = sizeof(device); image=(Image *) NULL; while(EnumDisplayDevices(NULL,i,&device,0) && ++i) { if ((device.StateFlags & DISPLAY_DEVICE_ACTIVE) != DISPLAY_DEVICE_ACTIVE) continue; hDC=CreateDC(device.DeviceName,device.DeviceName,NULL,NULL); if (hDC == (HDC) NULL) ThrowReaderException(CoderError,"UnableToCreateDC"); screen=AcquireImage(image_info); screen->columns=(size_t) GetDeviceCaps(hDC,HORZRES); screen->rows=(size_t) GetDeviceCaps(hDC,VERTRES); screen->storage_class=DirectClass; status=SetImageExtent(screen,screen->columns,screen->rows); if (status == MagickFalse) { InheritException(exception,&image->exception); return(DestroyImageList(image)); } if (image == (Image *) NULL) image=screen; else AppendImageToList(&image,screen); bitmapDC=CreateCompatibleDC(hDC); if (bitmapDC == (HDC) NULL) { DeleteDC(hDC); ThrowReaderException(CoderError,"UnableToCreateDC"); } (void) ResetMagickMemory(&bmi,0,sizeof(BITMAPINFO)); bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth=(LONG) screen->columns; bmi.bmiHeader.biHeight=(-1)*(LONG) screen->rows; bmi.bmiHeader.biPlanes=1; bmi.bmiHeader.biBitCount=24; bmi.bmiHeader.biCompression=BI_RGB; bitmap=CreateDIBSection(hDC,&bmi,DIB_RGB_COLORS,(void **) &p,NULL,0); if (bitmap == (HBITMAP) NULL) { DeleteDC(hDC); DeleteDC(bitmapDC); ThrowReaderException(CoderError,"UnableToCreateBitmap"); } bitmapOld=(HBITMAP) SelectObject(bitmapDC,bitmap); if (bitmapOld == (HBITMAP) NULL) { DeleteDC(hDC); DeleteDC(bitmapDC); DeleteObject(bitmap); ThrowReaderException(CoderError,"UnableToCreateBitmap"); } BitBlt(bitmapDC,0,0,(int) screen->columns,(int) screen->rows,hDC,0,0, SRCCOPY); (void) SelectObject(bitmapDC,bitmapOld); for (y=0; y < (ssize_t) screen->rows; y++) { q=QueueAuthenticPixels(screen,0,y,screen->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) screen->columns; x++) { SetPixelRed(q,ScaleCharToQuantum(p->rgbtRed)); SetPixelGreen(q,ScaleCharToQuantum(p->rgbtGreen)); SetPixelBlue(q,ScaleCharToQuantum(p->rgbtBlue)); SetPixelOpacity(q,OpaqueOpacity); p++; q++; } if (SyncAuthenticPixels(screen,exception) == MagickFalse) break; } DeleteDC(hDC); DeleteDC(bitmapDC); DeleteObject(bitmap); } } #elif defined(MAGICKCORE_X11_DELEGATE) { const char *option; XImportInfo ximage_info; (void) exception; XGetImportInfo(&ximage_info); option=GetImageOption(image_info,"x:screen"); if (option != (const char *) NULL) ximage_info.screen=IsMagickTrue(option); option=GetImageOption(image_info,"x:silent"); if (option != (const char *) NULL) ximage_info.silent=IsMagickTrue(option); image=XImportImage(image_info,&ximage_info); } #endif return(image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C l o n e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CloneImages() clones one or more images from an image sequence, using a % comma separated list of image numbers or ranges. % % The numbers start at 0 for the first image in the list, while negative % numbers refer to images starting counting from the end of the range. Images % may be refered to multiple times to clone them multiple times. Images % refered beyond the available number of images in list are ignored. % % Images referenced may be reversed, and results in a clone of those images % also being made with a reversed order. % % The format of the CloneImages method is: % % Image *CloneImages(const Image *images,const char *scenes, % ExceptionInfo *exception) % % A description of each parameter follows: % % o images: the image sequence. % % o scenes: This character string specifies which scenes to clone % (e.g. 1,3-5,7-3,2). % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *CloneImages(const Image *images,const char *scenes, ExceptionInfo *exception) { char *p; const Image *next; Image *clone_images, *image; long first, last, step; register long i; size_t length; assert(images != (const Image *) NULL); assert(images->signature == MagickSignature); assert(scenes != (char *) NULL); if (images->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); clone_images=NewImageList(); images=GetFirstImageInList(images); length=GetImageListLength(images); for (p=(char *) scenes; *p != '\0';) { while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ',')) p++; first=strtol(p,&p,10); if (first < 0) first+=(long) length; last=first; while (isspace((int) ((unsigned char) *p)) != 0) p++; if (*p == '-') { last=strtol(p+1,&p,10); if (last < 0) last+=(long) length; } for (step=first > last ? -1 : 1; first != (last+step); first+=step) { i=0; for (next=images; next != (Image *) NULL; next=GetNextImageInList(next)) { if (i == first) { image=CloneImage(next,0,0,MagickTrue,exception); if (image == (Image *) NULL) break; AppendImageToList(&clone_images,image); } i++; } } } return(GetFirstImageInList(clone_images)); }
MagickExport MagickBooleanType ImportImageCommand(ImageInfo *image_info, int argc,char **argv,char **magick_unused(metadata),ExceptionInfo *exception) { #if defined(HasX11) #define DestroyImport() \ { \ XDestroyResourceInfo(&resource_info); \ if (display != (Display *) NULL) \ { \ XCloseDisplay(display); \ display=(Display *) NULL; \ } \ for ( ; k >= 0; k--) \ image_stack[k]=DestroyImageList(image_stack[k]); \ for (i=0; i < (long) argc; i++) \ argv[i]=(char *) RelinquishMagickMemory(argv[i]); \ argv=(char **) RelinquishMagickMemory(argv); \ } #define ThrowImportException(asperity,tag,option) \ { \ if (exception->severity == UndefinedException) \ (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \ "`%s'",option); \ DestroyImport(); \ return(MagickFalse); \ } #define ThrowImportInvalidArgumentException(option,argument) \ { \ (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \ "InvalidArgument","`%s': %s",argument,option); \ DestroyImport(); \ return(MagickFalse); \ } char *filename, *option, *resource_value, *server_name, *target_window; Display *display; Image *image_stack[MaxImageStackDepth+1]; long j, k, snapshots; MagickStatusType pend, status; QuantizeInfo *quantize_info; register long i; XImportInfo ximage_info; XResourceInfo resource_info; XrmDatabase resource_database; /* Set defaults. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(exception != (ExceptionInfo *) NULL); display=(Display *) NULL; j=1; k=0; image_stack[k]=NewImageList(); option=(char *) NULL; pend=MagickFalse; resource_database=(XrmDatabase) NULL; (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info)); server_name=(char *) NULL; status=MagickTrue; SetNotifyHandlers; /* Check for server name specified on the command line. */ ReadCommandlLine(argc,&argv); status=ExpandFilenames(&argc,&argv); if (status == MagickFalse) ThrowImportException(ResourceLimitError,"MemoryAllocationFailed", strerror(errno)); for (i=1; i < (long) argc; i++) { /* Check command line for server name. */ option=argv[i]; if (IsMagickOption(option) == MagickFalse) continue; if (LocaleCompare("display",option+1) == 0) { /* User specified server name. */ i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); server_name=argv[i]; break; } } /* Get user defaults from X resource database. */ display=XOpenDisplay(server_name); if (display == (Display *) NULL) ThrowImportException(XServerError,"UnableToOpenXServer", XDisplayName(server_name)); (void) XSetErrorHandler(XError); resource_database=XGetResourceDatabase(display,GetClientName()); XGetImportInfo(&ximage_info); XGetResourceInfo(resource_database,GetClientName(),&resource_info); image_info=resource_info.image_info; quantize_info=resource_info.quantize_info; resource_value=XGetResourceInstance(resource_database,GetClientName(), "border","False"); ximage_info.borders=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "delay","0"); resource_info.delay=(unsigned int) atoi(resource_value); image_info->density=XGetResourceInstance(resource_database,GetClientName(), "density",(char *) NULL); resource_value=XGetResourceInstance(resource_database,GetClientName(), "descend","True"); ximage_info.descend=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "frame","False"); ximage_info.frame=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "interlace","none"); image_info->interlace=UndefinedInterlace; if (LocaleCompare("None",resource_value) == 0) image_info->interlace=NoInterlace; if (LocaleCompare("Line",resource_value) == 0) image_info->interlace=LineInterlace; if (LocaleCompare("Plane",resource_value) == 0) image_info->interlace=PlaneInterlace; if (LocaleCompare("Partition",resource_value) == 0) image_info->interlace=PartitionInterlace; if (image_info->interlace == UndefinedInterlace) ThrowImportException(OptionError,"Unrecognized interlace type", resource_value); image_info->page=XGetResourceInstance(resource_database,GetClientName(), "pageGeometry",(char *) NULL); resource_value=XGetResourceInstance(resource_database,GetClientName(), "pause","0"); resource_info.pause=(unsigned int) atol(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "quality","85"); image_info->quality=(unsigned long) atol(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "screen","False"); ximage_info.screen=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "silent","False"); ximage_info.silent=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "verbose","False"); image_info->verbose=IsTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "dither","True"); quantize_info->dither=IsTrue(resource_value); snapshots=1; status=MagickTrue; filename=(char *) NULL; target_window=(char *) NULL; /* Check command syntax. */ for (i=1; i < (long) argc; i++) { option=argv[i]; if (LocaleCompare(option,"(") == 0) { if (k == MaxImageStackDepth) ThrowImportException(OptionError,"ParenthesisNestedTooDeeply", option); MogrifyImageStack(image_stack[k],MagickTrue,pend); k++; image_stack[k]=NewImageList(); continue; } if (LocaleCompare(option,")") == 0) { if (k == 0) ThrowImportException(OptionError,"UnableToParseExpression",option); if (image_stack[k] != (Image *) NULL) { MogrifyImageStack(image_stack[k],MagickTrue,MagickTrue); AppendImageToList(&image_stack[k-1],image_stack[k]); } k--; continue; } if (IsMagickOption(option) == MagickFalse) { Image *image; unsigned long scene; /* Read image from X server. */ MogrifyImageStack(image_stack[k],MagickFalse,pend); filename=argv[i]; if (target_window != (char *) NULL) (void) CopyMagickString(image_info->filename,target_window, MaxTextExtent); for (scene=0; scene < (unsigned long) Max(snapshots,1); scene++) { (void) sleep(resource_info.pause); image=XImportImage(image_info,&ximage_info); status&=(image != (Image *) NULL) && (exception->severity < ErrorException); if (image == (Image *) NULL) continue; (void) CopyMagickString(image->filename,filename,MaxTextExtent); (void) strcpy(image->magick,"PS"); image->scene=scene; AppendImageToList(&image_stack[k],image); MogrifyImageStack(image_stack[k],MagickFalse,MagickTrue); } continue; } pend=image_stack[k] != (Image *) NULL ? MagickTrue : MagickFalse; switch(*(option+1)) { case 'a': { if (LocaleCompare("adjoin",option+1) == 0) break; if (LocaleCompare("annotate",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); if (i == (long) (argc-1)) ThrowImportException(OptionError,"MissingArgument",option); i++; break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'b': { if (LocaleCompare("border",option+1) == 0) { ximage_info.borders=(MagickBooleanType) (*option == '-'); (void) strcpy(argv[i]+1,"{0}"); break; } if (LocaleCompare("bordercolor",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'c': { if (LocaleCompare("cache",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("channel",option+1) == 0) { long channel; if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowImportException(OptionError,"MissingArgument",option); channel=ParseChannelOption(argv[i]); if (channel < 0) ThrowImportException(OptionError,"UnrecognizedChannelType", argv[i]); break; } if (LocaleCompare("colors",option+1) == 0) { quantize_info->number_colors=0; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); quantize_info->number_colors=(unsigned long) atol(argv[i]); break; } if (LocaleCompare("colorspace",option+1) == 0) { long colorspace; quantize_info->colorspace=UndefinedColorspace; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); colorspace=ParseMagickOption(MagickColorspaceOptions,MagickFalse, argv[i]); if (colorspace < 0) ThrowImportException(OptionError,"UnrecognizedColorspace", argv[i]); quantize_info->colorspace=(ColorspaceType) colorspace; if (quantize_info->colorspace == GRAYColorspace) { quantize_info->colorspace=GRAYColorspace; quantize_info->number_colors=256; quantize_info->tree_depth=8; } break; } if (LocaleCompare("comment",option+1) == 0) { if (*option == '-') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); status=SetImageOption(image_info,"Comment",argv[i]); if (status == MagickFalse) ThrowImportException(OptionError,"UnrecognizedOption",argv[i]); break; } if (LocaleCompare("compress",option+1) == 0) { long compression; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); compression=ParseMagickOption(MagickCompressionOptions, MagickFalse,argv[i]); if (compression < 0) ThrowImportException(OptionError,"UnrecognizedImageCompression", argv[i]); break; } if (LocaleCompare("crop",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'd': { if (LocaleCompare("debug",option+1) == 0) { LogEventType event_mask; (void) SetLogEventMask("None"); if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); event_mask=SetLogEventMask(argv[i]); if (event_mask == UndefinedEvents) ThrowImportException(OptionError,"UnrecognizedEventType",option); break; } if (LocaleCompare("define",option+1) == 0) { i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (*option == '+') { const char *define; define=GetImageOption(image_info,argv[i]); if (define == (char *) NULL) ThrowImportException(OptionError,"NoSuchOption",argv[i]); break; } break; } if (LocaleCompare("delay",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); status=SetImageOption(image_info,"delay",argv[i]); if (status == MagickFalse) ThrowImportException(OptionError,"UnrecognizedOption",argv[i]); break; } if (LocaleCompare("density",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("depth",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("descend",option+1) == 0) { ximage_info.descend=(MagickBooleanType) (*option == '-'); break; } if (LocaleCompare("display",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("dispose",option+1) == 0) { long dispose; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); dispose=ParseMagickOption(MagickDisposeOptions,MagickFalse,argv[i]); if (dispose < 0) ThrowImportException(OptionError,"UnrecognizedDisposeMethod", argv[i]); break; } if (LocaleCompare("dither",option+1) == 0) { quantize_info->dither=(MagickBooleanType) (*option == '-'); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'e': { if (LocaleCompare("encoding",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("endian",option+1) == 0) { long endian; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); endian=ParseMagickOption(MagickEndianOptions,MagickFalse, argv[i]); if (endian < 0) ThrowImportException(OptionError,"UnrecognizedEndianType", argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'f': { if (LocaleCompare("frame",option+1) == 0) { ximage_info.frame=(MagickBooleanType) (*option == '-'); (void) strcpy(argv[i]+1,"{0}"); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'g': { if (LocaleCompare("geometry",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("gravity",option+1) == 0) { long gravity; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); gravity=ParseMagickOption(MagickGravityOptions,MagickFalse,argv[i]); if (gravity < 0) ThrowImportException(OptionError,"UnrecognizedGravityType", argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'h': { if (LocaleCompare("help",option+1) == 0) ImportUsage(); ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'i': { if (LocaleCompare("interlace",option+1) == 0) { long interlace; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); interlace=ParseMagickOption(MagickInterlaceOptions,MagickFalse, argv[i]); if (interlace < 0) ThrowImportException(OptionError,"UnrecognizedInterlaceType", argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'l': { if (LocaleCompare("label",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); status=SetImageOption(image_info,"label",argv[i]); if (status == MagickFalse) ThrowImportException(OptionError,"UnrecognizedOption",argv[i]); break; } if (LocaleCompare("limit",option+1) == 0) { long resource; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); resource=ParseMagickOption(MagickResourceOptions,MagickFalse, argv[i]); if (resource < 0) ThrowImportException(OptionError,"UnrecognizedResourceType", argv[i]); i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if ((LocaleCompare("unlimited",argv[i]) != 0) && (IsGeometry(argv[i]) == MagickFalse)) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("log",option+1) == 0) { if (*option == '+') break; i++; if ((i == (long) argc) || (strchr(argv[i],'%') == (char *) NULL)) ThrowImportException(OptionError,"MissingArgument",option); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'm': { if (LocaleCompare("monitor",option+1) == 0) break; if (LocaleCompare("monochrome",option+1) == 0) { if (*option == '+') break; quantize_info->number_colors=2; quantize_info->tree_depth=8; quantize_info->colorspace=GRAYColorspace; break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'n': { if (LocaleCompare("negate",option+1) == 0) break; ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'p': { if (LocaleCompare("page",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); status=SetImageOption(image_info,"page",argv[i]); if (status == MagickFalse) ThrowImportException(OptionError,"UnrecognizedOption",argv[i]); break; } if (LocaleCompare("pause",option+1) == 0) { resource_info.pause=0; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); resource_info.pause=(unsigned int) atoi(argv[i]); break; } if (LocaleCompare("ping",option+1) == 0) ThrowImportException(OptionError,"DeprecatedOption",option); if (LocaleCompare("pointsize",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'q': { if (LocaleCompare("quality",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("quiet",option+1) == 0) break; ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'r': { if (LocaleCompare("repage",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("resize",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("rotate",option+1) == 0) { i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 's': { if (LocaleCompare("sampling-factor",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("scene",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("set",option+1) == 0) { i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("screen",option+1) == 0) { ximage_info.screen=(MagickBooleanType) (*option == '-'); break; } if (LocaleCompare("silent",option+1) == 0) { ximage_info.silent=(MagickBooleanType) (*option == '-'); break; } if (LocaleCompare("snaps",option+1) == 0) { (void) strcpy(argv[i]+1,"{1}"); i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); snapshots=atol(argv[i]); break; } if (LocaleCompare("strip",option+1) == 0) break; if (LocaleCompare("support",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 't': { if (LocaleCompare("thumnail",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("transparent",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("treedepth",option+1) == 0) { quantize_info->tree_depth=0; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowImportInvalidArgumentException(option,argv[i]); quantize_info->tree_depth=(unsigned long) atol(argv[i]); break; } if (LocaleCompare("trim",option+1) == 0) break; if (LocaleCompare("type",option+1) == 0) { long type; if (*option == '+') break; i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); type=ParseMagickOption(MagickImageOptions,MagickFalse,argv[i]); if (type < 0) ThrowImportException(OptionError,"UnrecognizedImageType",argv[i]); break; } ThrowImportException(OptionError,"UnrecognizedOption",option); } case 'w': { i++; if (i == (long) argc) ThrowImportException(OptionError,"MissingArgument",option); (void) CloneString(&target_window,argv[i]); break; } case 'v': { if (LocaleCompare("verbose",option+1) == 0) break; if (LocaleCompare("version",option+1) == 0) break; ThrowImportException(OptionError,"UnrecognizedOption",option); } case '?': break; default: ThrowImportException(OptionError,"UnrecognizedOption",option); } status=(MagickStatusType) ParseMagickOption(MagickMogrifyOptions,MagickFalse,option+1); if (status == MagickTrue) MogrifyImageStack(image_stack[k],MagickTrue,MagickTrue); } if (k != 0) ThrowImportException(OptionError,"UnbalancedParenthesis",argv[i]); if (i != argc) ThrowImportException(OptionError,"MissingAnImageFilename",argv[i]); if (image_stack[k] == (Image *) NULL) ThrowImportException(OptionError,"MissingAnImageFilename",argv[argc-1]); MogrifyImageStack(image_stack[k],MagickTrue,MagickTrue) GetImageException(image_stack[k],exception); status&=WriteImages(image_info,image_stack[k],filename,exception); DestroyImport(); return(status != 0 ? MagickTrue : MagickFalse); #else (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, "XWindowLibraryIsNotAvailable","`%s'",image_info->filename); ImportUsage(); return(MagickFalse); #endif }
WandExport MagickBooleanType IdentifyImageCommand(ImageInfo *image_info, int argc,char **argv,char **metadata,ExceptionInfo *exception) { #define DestroyIdentify() \ { \ for ( ; k >= 0; k--) \ image_stack[k]=DestroyImageList(image_stack[k]); \ for (i=0; i < (long) argc; i++) \ argv[i]=DestroyString(argv[i]); \ argv=(char **) RelinquishMagickMemory(argv); \ } #define ThrowIdentifyException(asperity,tag,option) \ { \ if (exception->severity == UndefinedException) \ (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \ "`%s'",option); \ DestroyIdentify(); \ return(MagickFalse); \ } #define ThrowIdentifyInvalidArgumentException(option,argument) \ { \ (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \ "InvalidArgument","`%s': %s",argument,option); \ DestroyIdentify(); \ return(MagickFalse); \ } const char *format, *option; Image *image_stack[MaxImageStackDepth+1]; long j, k; MagickBooleanType fire, pend; MagickStatusType status; register long i; unsigned long count; /* Set defaults. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(exception != (ExceptionInfo *) NULL); if (argc < 2) IdentifyUsage(); count=0; format=NULL; j=1; k=0; image_stack[k]=NewImageList(); option=(char *) NULL; pend=MagickFalse; status=MagickTrue; /* Identify an image. */ ReadCommandlLine(argc,&argv); status=ExpandFilenames(&argc,&argv); if (status == MagickFalse) { char *message; message=GetExceptionMessage(errno); ThrowIdentifyException(ResourceLimitError,"MemoryAllocationFailed", message); message=DestroyString(message); } for (i=1; i < (long) argc; i++) { option=argv[i]; if (LocaleCompare(option,"(") == 0) { if (k == MaxImageStackDepth) ThrowIdentifyException(OptionError,"ParenthesisNestedTooDeeply", option); MogrifyImageStack(image_stack[k],MagickTrue,pend); k++; image_stack[k]=NewImageList(); continue; } if (LocaleCompare(option,")") == 0) { if (k == 0) ThrowIdentifyException(OptionError,"UnableToParseExpression",option); if (image_stack[k] != (Image *) NULL) { MogrifyImageStack(image_stack[k],MagickTrue,MagickTrue); AppendImageToList(&image_stack[k-1],image_stack[k]); } k--; continue; } if (IsMagickOption(option) == MagickFalse) { char *filename; Image *image; ImageInfo *identify_info; /* Read input image. */ MogrifyImageStack(image_stack[k],MagickFalse,pend); identify_info=CloneImageInfo(image_info); identify_info->verbose=MagickFalse; filename=argv[i]; if ((LocaleCompare(filename,"--") == 0) && (i < (argc-1))) filename=argv[++i]; (void) CopyMagickString(identify_info->filename,filename,MaxTextExtent); if (identify_info->ping == MagickFalse) image=ReadImage(identify_info,exception); else image=PingImage(identify_info,exception); identify_info=DestroyImageInfo(identify_info); status&=(image != (Image *) NULL) && (exception->severity < ErrorException); if (image == (Image *) NULL) continue; AppendImageToList(&image_stack[k],image); MogrifyImageStack(image_stack[k],MagickFalse,MagickTrue); image=image_stack[k]; for ( ; image != (Image *) NULL; image=GetNextImageInList(image)) { if (image->scene == 0) image->scene=count++; if (format == (char *) NULL) { (void) IdentifyImage(image,stdout,image_info->verbose); continue; } if (metadata != (char **) NULL) { char *text; text=InterpretImageProperties(image_info,image,format); if (text == (char *) NULL) { char *message; message=GetExceptionMessage(errno); ThrowIdentifyException(ResourceLimitError, "MemoryAllocationFailed",message); message=DestroyString(message); } (void) ConcatenateString(&(*metadata),text); text=DestroyString(text); if (LocaleCompare(format,"%n") == 0) break; } } image_stack[k]=DestroyImageList(image_stack[k]); continue; } pend=image_stack[k] != (Image *) NULL ? MagickTrue : MagickFalse; switch (*(option+1)) { case 'a': { if (LocaleCompare("alpha",option+1) == 0) { long type; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); type=ParseMagickOption(MagickAlphaOptions,MagickFalse,argv[i]); if (type < 0) ThrowIdentifyException(OptionError,"UnrecognizedAlphaChannelType", argv[i]); break; } if (LocaleCompare("antialias",option+1) == 0) break; if (LocaleCompare("authenticate",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'c': { if (LocaleCompare("cache",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("channel",option+1) == 0) { long channel; if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); channel=ParseChannelOption(argv[i]); if (channel < 0) ThrowIdentifyException(OptionError,"UnrecognizedChannelType", argv[i]); break; } if (LocaleCompare("colorspace",option+1) == 0) { long colorspace; if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); colorspace=ParseMagickOption(MagickColorspaceOptions, MagickFalse,argv[i]); if (colorspace < 0) ThrowIdentifyException(OptionError,"UnrecognizedColorspace", argv[i]); break; } if (LocaleCompare("crop",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); image_info->ping=MagickFalse; break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'd': { if (LocaleCompare("debug",option+1) == 0) { long event; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); event=ParseMagickOption(MagickLogEventOptions,MagickFalse,argv[i]); if (event < 0) ThrowIdentifyException(OptionError,"UnrecognizedEventType", argv[i]); (void) SetLogEventMask(argv[i]); break; } if (LocaleCompare("define",option+1) == 0) { i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (*option == '+') { const char *define; define=GetImageOption(image_info,argv[i]); if (define == (const char *) NULL) ThrowIdentifyException(OptionError,"NoSuchOption",argv[i]); break; } break; } if (LocaleCompare("density",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("depth",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'f': { if (LocaleCompare("format",option+1) == 0) { format=(char *) NULL; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); format=argv[i]; break; } if (LocaleCompare("fuzz",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'g': { if (LocaleCompare("gamma",option+1) == 0) { i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'h': { if ((LocaleCompare("help",option+1) == 0) || (LocaleCompare("-help",option+1) == 0)) IdentifyUsage(); ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'i': { if (LocaleCompare("interlace",option+1) == 0) { long interlace; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); interlace=ParseMagickOption(MagickInterlaceOptions,MagickFalse, argv[i]); if (interlace < 0) ThrowIdentifyException(OptionError, "UnrecognizedInterlaceType",argv[i]); break; } if (LocaleCompare("interpolate",option+1) == 0) { long interpolate; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); interpolate=ParseMagickOption(MagickInterpolateOptions,MagickFalse, argv[i]); if (interpolate < 0) ThrowIdentifyException(OptionError, "UnrecognizedInterpolateMethod",argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'l': { if (LocaleCompare("limit",option+1) == 0) { long resource; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); resource=ParseMagickOption(MagickResourceOptions,MagickFalse, argv[i]); if (resource < 0) ThrowIdentifyException(OptionError,"UnrecognizedResourceType", argv[i]); i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if ((LocaleCompare("unlimited",argv[i]) != 0) && (IsGeometry(argv[i]) == MagickFalse)) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("list",option+1) == 0) { long list; if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); list=ParseMagickOption(MagickListOptions,MagickFalse,argv[i]); if (list < 0) ThrowIdentifyException(OptionError,"UnrecognizedListType", argv[i]); (void) MogrifyImageInfo(image_info,(int) (i-j+1),(const char **) argv+j,exception); DestroyIdentify(); return(MagickTrue); } if (LocaleCompare("log",option+1) == 0) { if (*option == '+') break; i++; if ((i == (long) argc) || (strchr(argv[i],'%') == (char *) NULL)) ThrowIdentifyException(OptionError,"MissingArgument",option); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'm': { if (LocaleCompare("matte",option+1) == 0) break; if (LocaleCompare("monitor",option+1) == 0) break; ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'p': { if (LocaleCompare("ping",option+1) == 0) break; ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'q': { if (LocaleCompare("quiet",option+1) == 0) break; ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'r': { if (LocaleCompare("regard-warnings",option+1) == 0) break; ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 's': { if (LocaleCompare("sampling-factor",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("seed",option+1) == 0) { unsigned long seed; if (*option == '+') { seed=(unsigned long) time((time_t *) NULL); SeedRandomReservoir(seed); break; } i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); seed=(unsigned long) atol(argv[i]); SeedRandomReservoir(seed); break; } if (LocaleCompare("set",option+1) == 0) { i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); break; } if (LocaleCompare("size",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } if (LocaleCompare("strip",option+1) == 0) break; if (LocaleCompare("support",option+1) == 0) { if (*option == '+') break; i++; if (i == (long) argc) ThrowIdentifyException(OptionError,"MissingArgument",option); if (IsGeometry(argv[i]) == MagickFalse) ThrowIdentifyInvalidArgumentException(option,argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'u': { if (LocaleCompare("units",option+1) == 0) { long units; if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); units=ParseMagickOption(MagickResolutionOptions,MagickFalse, argv[i]); if (units < 0) ThrowIdentifyException(OptionError,"UnrecognizedUnitsType", argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case 'v': { if (LocaleCompare("verbose",option+1) == 0) break; if ((LocaleCompare("version",option+1) == 0) || (LocaleCompare("-version",option+1) == 0)) { (void) fprintf(stdout,"Version: %s\n", GetMagickVersion((unsigned long *) NULL)); (void) fprintf(stdout,"Copyright: %s\n\n",GetMagickCopyright()); break; } if (LocaleCompare("virtual-pixel",option+1) == 0) { long method; if (*option == '+') break; i++; if (i == (long) (argc-1)) ThrowIdentifyException(OptionError,"MissingArgument",option); method=ParseMagickOption(MagickVirtualPixelOptions,MagickFalse, argv[i]); if (method < 0) ThrowIdentifyException(OptionError, "UnrecognizedVirtualPixelMethod",argv[i]); break; } ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } case '?': break; default: ThrowIdentifyException(OptionError,"UnrecognizedOption",option) } fire=(MagickBooleanType) ParseMagickOption(MagickMogrifyOptions, MagickFalse,option+1); if (fire == MagickTrue) MogrifyImageStack(image_stack[k],MagickTrue,MagickTrue); } if (k != 0) ThrowIdentifyException(OptionError,"UnbalancedParenthesis",argv[i]); if (i != argc) ThrowIdentifyException(OptionError,"MissingAnImageFilename",argv[i]); DestroyIdentify(); return(status != 0 ? MagickTrue : MagickFalse); }
int tc_filter(frame_list_t *ptr_, char *options) { vframe_list_t *ptr = (vframe_list_t *)ptr_; vob_t *vob = NULL; int instance = ptr->filter_id; MyFilterData *mfd = mfd_all[instance]; if (mfd != NULL) { vob = mfd->vob; } //---------------------------------- // // filter init // //---------------------------------- if (ptr->tag & TC_FILTER_GET_CONFIG) { optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYO", "1"); // buf, name, comment, format, val, from, to optstr_param(options, "file", "Image filename", "%s", "logo.png"); optstr_param(options, "posdef", "Position (0=None, 1=TopL, 2=TopR, 3=BotL, 4=BotR, 5=Center)", "%d", "0", "0", "5"); optstr_param(options, "pos", "Position (0-width x 0-height)", "%dx%d", "0x0", "0", "width", "0", "height"); optstr_param(options, "range", "Restrict rendering to framerange", "%u-%u", "0-0", "0", "oo", "0", "oo"); optstr_param(options, "fade", "Fade image in/out (# of frames)", "%u-%u", "0-0", "0", "oo", "0", "oo"); // bools optstr_param(options, "ignoredelay", "Ignore delay specified in animations", "", "0"); optstr_param(options, "rgbswap", "Swap red/blue colors", "", "0"); optstr_param(options, "grayout", "YUV only: don't write Cb and Cr, makes a nice effect", "", "0"); optstr_param(options, "hqconv", "YUV only: do high quality rgb->yuv img conversion", "", "0"); optstr_param(options, "flip", "Mirror image", "", "0"); return 0; } if (ptr->tag & TC_FILTER_INIT) { Image *timg; Image *nimg; ImageInfo *image_info; ExceptionInfo exception_info; int rgb_off = 0; vob_t *tmpvob; tmpvob = tc_get_vob(); if (tmpvob == NULL) return -1; mfd_all[instance] = tc_zalloc(sizeof(MyFilterData)); if (mfd_all[instance] == NULL) return -1; mfd = mfd_all[instance]; strlcpy(mfd->file, "logo.png", PATH_MAX); mfd->end = (unsigned int)-1; mfd->vob = tmpvob; vob = mfd->vob; if (options != NULL) { if (verbose) tc_log_info(MOD_NAME, "options=%s", options); optstr_get(options, "file", "%[^:]", mfd->file); optstr_get(options, "posdef", "%d", (int *)&mfd->pos); optstr_get(options, "pos", "%dx%d", &mfd->posx, &mfd->posy); optstr_get(options, "range", "%u-%u", &mfd->start, &mfd->end); optstr_get(options, "fade", "%u-%u", &mfd->fadein, &mfd->fadeout); if (optstr_lookup(options, "ignoredelay") != NULL) mfd->ignoredelay = !mfd->ignoredelay; if (optstr_lookup(options, "flip") != NULL) mfd->flip = !mfd->flip; if (optstr_lookup(options, "rgbswap") != NULL) mfd->rgbswap = !mfd->rgbswap; if (optstr_lookup(options, "grayout") != NULL) mfd->grayout = !mfd->grayout; if (optstr_lookup(options, "hqconv") != NULL) mfd->hqconv = !mfd->hqconv; if (optstr_lookup (options, "help") != NULL) flogo_help_optstr(); } if (verbose > 1) { tc_log_info(MOD_NAME, " Logo renderer Settings:"); tc_log_info(MOD_NAME, " file = %s", mfd->file); tc_log_info(MOD_NAME, " posdef = %d", mfd->pos); tc_log_info(MOD_NAME, " pos = %dx%d", mfd->posx, mfd->posy); tc_log_info(MOD_NAME, " range = %u-%u", mfd->start, mfd->end); tc_log_info(MOD_NAME, " fade = %u-%u", mfd->fadein, mfd->fadeout); tc_log_info(MOD_NAME, " flip = %d", mfd->flip); tc_log_info(MOD_NAME, " ignoredelay = %d", mfd->ignoredelay); tc_log_info(MOD_NAME, " rgbswap = %d", mfd->rgbswap); tc_log_info(MOD_NAME, " grayout = %d", mfd->grayout); tc_log_info(MOD_NAME, " hqconv = %d", mfd->hqconv); } /* Transcode serializes module execution, so this does not need a * semaphore. */ magick_usecount++; if (!IsMagickInstantiated()) { InitializeMagick(""); } GetExceptionInfo(&exception_info); image_info = CloneImageInfo((ImageInfo *) NULL); strlcpy(image_info->filename, mfd->file, MaxTextExtent); mfd->image = ReadImage(image_info, &exception_info); if (mfd->image == (Image *) NULL) { MagickWarning(exception_info.severity, exception_info.reason, exception_info.description); strlcpy(mfd->file, "/dev/null", PATH_MAX); return 0; } DestroyImageInfo(image_info); if (mfd->image->columns > vob->ex_v_width || mfd->image->rows > vob->ex_v_height ) { tc_log_error(MOD_NAME, "\"%s\" is too large", mfd->file); return -1; } if (vob->im_v_codec == TC_CODEC_YUV420P) { if ((mfd->image->columns & 1) || (mfd->image->rows & 1)) { tc_log_error(MOD_NAME, "\"%s\" has odd sizes", mfd->file); return -1; } } mfd->images = (Image *)GetFirstImageInList(mfd->image); nimg = NewImageList(); while (mfd->images != (Image *)NULL) { if (mfd->flip || flip) { timg = FlipImage(mfd->images, &exception_info); if (timg == (Image *) NULL) { MagickError(exception_info.severity, exception_info.reason, exception_info.description); return -1; } AppendImageToList(&nimg, timg); } mfd->images = GetNextImageInList(mfd->images); mfd->nr_of_images++; } // check for memleaks; //DestroyImageList(image); if (mfd->flip || flip) { mfd->image = nimg; } /* initial delay. real delay = 1/100 sec * delay */ mfd->cur_delay = mfd->image->delay*vob->fps/100; if (verbose & TC_DEBUG) tc_log_info(MOD_NAME, "Nr: %d Delay: %d mfd->image->del %lu|", mfd->nr_of_images, mfd->cur_delay, mfd->image->delay); if (vob->im_v_codec == TC_CODEC_YUV420P) { /* convert Magick RGB image format to YUV */ /* todo: convert the magick image if it's not rgb! (e.g. cmyk) */ Image *image; uint8_t *yuv_hqbuf = NULL; /* Round up for odd-size images */ unsigned long width = mfd->image->columns; unsigned long height = mfd->image->rows; int do_rgbswap = (rgbswap || mfd->rgbswap); int i; /* Allocate buffers for the YUV420P frames. mfd->nr_of_images * will be 1 unless this is an animated GIF or MNG. * This buffer needs to be large enough to store a temporary * 24-bit RGB image (extracted from the ImageMagick handle). */ mfd->yuv = flogo_yuvbuf_alloc(width*height * 3, mfd->nr_of_images); if (mfd->yuv == NULL) { tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__); return -1; } if (mfd->hqconv) { /* One temporary buffer, to hold full Y, U, and V planes. */ yuv_hqbuf = tc_malloc(width*height * 3); if (yuv_hqbuf == NULL) { tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__); return -1; } } mfd->tcvhandle = tcv_init(); if (mfd->tcvhandle == NULL) { tc_log_error(MOD_NAME, "image conversion init failed"); return -1; } image = GetFirstImageInList(mfd->image); for (i = 0; i < mfd->nr_of_images; i++) { if (!mfd->hqconv) { flogo_convert_image(mfd->tcvhandle, image, mfd->yuv[i], IMG_YUV420P, do_rgbswap); } else { flogo_convert_image(mfd->tcvhandle, image, yuv_hqbuf, IMG_YUV444P, do_rgbswap); // Copy over Y data from the 444 image ac_memcpy(mfd->yuv[i], yuv_hqbuf, width * height); // Resize U plane by 1/2 in each dimension, into the // mfd YUV buffer tcv_zoom(mfd->tcvhandle, yuv_hqbuf + (width * height), mfd->yuv[i] + (width * height), width, height, 1, width / 2, height / 2, TCV_ZOOM_LANCZOS3 ); // Do the same with the V plane tcv_zoom(mfd->tcvhandle, yuv_hqbuf + 2*width*height, mfd->yuv[i] + width*height + (width/2)*(height/2), width, height, 1, width / 2, height / 2, TCV_ZOOM_LANCZOS3 ); } image = GetNextImageInList(image); } if (mfd->hqconv) tc_free(yuv_hqbuf); tcv_free(mfd->tcvhandle); } else { /* for RGB format is origin bottom left */ /* for RGB, rgbswap is done in the frame routine */ rgb_off = vob->ex_v_height - mfd->image->rows; mfd->posy = rgb_off - mfd->posy; } switch (mfd->pos) { case NONE: /* 0 */ break; case TOP_LEFT: mfd->posx = 0; mfd->posy = rgb_off; break; case TOP_RIGHT: mfd->posx = vob->ex_v_width - mfd->image->columns; break; case BOT_LEFT: mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off; break; case BOT_RIGHT: mfd->posx = vob->ex_v_width - mfd->image->columns; mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off; break; case CENTER: mfd->posx = (vob->ex_v_width - mfd->image->columns)/2; mfd->posy = (vob->ex_v_height- mfd->image->rows)/2; /* align to not cause color disruption */ if (mfd->posx & 1) mfd->posx++; if (mfd->posy & 1) mfd->posy++; break; } if (mfd->posy < 0 || mfd->posx < 0 || (mfd->posx + mfd->image->columns) > vob->ex_v_width || (mfd->posy + mfd->image->rows) > vob->ex_v_height) { tc_log_error(MOD_NAME, "invalid position"); return -1; } /* for running through image sequence */ mfd->images = mfd->image; /* Set up image/video coefficient lookup tables */ if (img_coeff_lookup[0] < 0) { int i; float maxrgbval = (float)MaxRGB; // from ImageMagick for (i = 0; i <= MAX_UINT8_VAL; i++) { float x = (float)ScaleCharToQuantum(i); /* Alternatively: * img_coeff = (maxrgbval - x) / maxrgbval; * vid_coeff = x / maxrgbval; */ img_coeff_lookup[i] = 1.0 - (x / maxrgbval); vid_coeff_lookup[i] = 1.0 - img_coeff_lookup[i]; } } // filter init ok. if (verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP); return 0; } //---------------------------------- // // filter close // //---------------------------------- if (ptr->tag & TC_FILTER_CLOSE) { if (mfd) { flogo_yuvbuf_free(mfd->yuv, mfd->nr_of_images); mfd->yuv = NULL; if (mfd->image) { DestroyImage(mfd->image); } tc_free(mfd); mfd = NULL; mfd_all[instance] = NULL; } magick_usecount--; if (magick_usecount == 0 && IsMagickInstantiated()) { DestroyMagick(); } return 0; } /* filter close */ //---------------------------------- // // filter frame routine // //---------------------------------- // tag variable indicates, if we are called before // transcodes internal video/audo frame processing routines // or after and determines video/audio context if ((ptr->tag & TC_POST_M_PROCESS) && (ptr->tag & TC_VIDEO) && !(ptr->attributes & TC_FRAME_IS_SKIPPED) ) { PixelPacket *pixel_packet; uint8_t *video_buf; int do_fade = 0; float fade_coeff = 0.0; float img_coeff, vid_coeff; /* Note: ImageMagick defines opacity = 0 as fully visible, and * opacity = MaxRGB as fully transparent. */ Quantum opacity; int row, col; if (ptr->id < mfd->start || ptr->id > mfd->end) return 0; if (strcmp(mfd->file, "/dev/null") == 0) return 0; if (ptr->id - mfd->start < mfd->fadein) { // fading-in fade_coeff = (float)(mfd->start - ptr->id + mfd->fadein) / (float)(mfd->fadein); do_fade = 1; } else if (mfd->end - ptr->id < mfd->fadeout) { // fading-out fade_coeff = (float)(ptr->id - mfd->end + mfd->fadeout) / (float)(mfd->fadeout); do_fade = 1; } mfd->cur_delay--; if (mfd->cur_delay < 0 || mfd->ignoredelay) { int seq; mfd->cur_seq = (mfd->cur_seq + 1) % mfd->nr_of_images; mfd->images = mfd->image; for (seq=0; seq<mfd->cur_seq; seq++) mfd->images = mfd->images->next; mfd->cur_delay = mfd->images->delay * vob->fps/100; } pixel_packet = GetImagePixels(mfd->images, 0, 0, mfd->images->columns, mfd->images->rows); if (vob->im_v_codec == TC_CODEC_RGB24) { unsigned long r_off, g_off, b_off; if (!(rgbswap || mfd->rgbswap)) { r_off = 0; b_off = 2; } else { r_off = 2; b_off = 0; } g_off = 1; for (row = 0; row < mfd->image->rows; row++) { video_buf = ptr->video_buf + 3 * ((row + mfd->posy) * vob->ex_v_width + mfd->posx); for (col = 0; col < mfd->image->columns; col++) { opacity = pixel_packet->opacity; if (do_fade) opacity += (Quantum)((MaxRGB - opacity) * fade_coeff); if (opacity == 0) { *(video_buf + r_off) = ScaleQuantumToChar(pixel_packet->red); *(video_buf + g_off) = ScaleQuantumToChar(pixel_packet->green); *(video_buf + b_off) = ScaleQuantumToChar(pixel_packet->blue); } else if (opacity < MaxRGB) { unsigned char opacity_uchar = ScaleQuantumToChar(opacity); img_coeff = img_coeff_lookup[opacity_uchar]; vid_coeff = vid_coeff_lookup[opacity_uchar]; *(video_buf + r_off) = (uint8_t)((*(video_buf + r_off)) * vid_coeff) + (uint8_t)(ScaleQuantumToChar(pixel_packet->red) * img_coeff); *(video_buf + g_off) = (uint8_t)((*(video_buf + g_off)) * vid_coeff) + (uint8_t)(ScaleQuantumToChar(pixel_packet->green) * img_coeff); *(video_buf + b_off) = (uint8_t)((*(video_buf + b_off)) * vid_coeff) + (uint8_t)(ScaleQuantumToChar(pixel_packet->blue) * img_coeff); } video_buf += 3; pixel_packet++; } } } else { /* !RGB */ unsigned long vid_size = vob->ex_v_width * vob->ex_v_height; unsigned long img_size = mfd->images->columns * mfd->images->rows; uint8_t *img_pixel_Y, *img_pixel_U, *img_pixel_V; uint8_t *vid_pixel_Y, *vid_pixel_U, *vid_pixel_V; img_pixel_Y = mfd->yuv[mfd->cur_seq]; img_pixel_U = img_pixel_Y + img_size; img_pixel_V = img_pixel_U + img_size/4; for (row = 0; row < mfd->images->rows; row++) { vid_pixel_Y = ptr->video_buf + (row + mfd->posy)*mfd->vob->ex_v_width + mfd->posx; vid_pixel_U = ptr->video_buf + vid_size + (row/2 + mfd->posy/2)*(mfd->vob->ex_v_width/2) + mfd->posx/2; vid_pixel_V = vid_pixel_U + vid_size/4; for (col = 0; col < mfd->images->columns; col++) { int do_UV_pixels = (mfd->grayout == 0 && !(row % 2) && !(col % 2)) ? 1 : 0; opacity = pixel_packet->opacity; if (do_fade) opacity += (Quantum)((MaxRGB - opacity) * fade_coeff); if (opacity == 0) { *vid_pixel_Y = *img_pixel_Y; if (do_UV_pixels) { *vid_pixel_U = *img_pixel_U; *vid_pixel_V = *img_pixel_V; } } else if (opacity < MaxRGB) { unsigned char opacity_uchar = ScaleQuantumToChar(opacity); img_coeff = img_coeff_lookup[opacity_uchar]; vid_coeff = vid_coeff_lookup[opacity_uchar]; *vid_pixel_Y = (uint8_t)(*vid_pixel_Y * vid_coeff) + (uint8_t)(*img_pixel_Y * img_coeff); if (do_UV_pixels) { *vid_pixel_U = (uint8_t)(*vid_pixel_U * vid_coeff) + (uint8_t)(*img_pixel_U * img_coeff); *vid_pixel_V = (uint8_t)(*vid_pixel_V * vid_coeff) + (uint8_t)(*img_pixel_V * img_coeff); } } vid_pixel_Y++; img_pixel_Y++; if (do_UV_pixels) { vid_pixel_U++; img_pixel_U++; vid_pixel_V++; img_pixel_V++; } pixel_packet++; } } } } return 0; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % P r e p e n d I m a g e T o L i s t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PrependImageToList() prepends the image to the beginning of the list. % % The format of the PrependImageToList method is: % % PrependImageToList(Image *images,Image *image) % % A description of each parameter follows: % % o images: the image list. % % o image: the image. % */ MagickExport void PrependImageToList(Image **images,Image *image) { AppendImageToList(&image,*images); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d X C F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadXCFImage() reads a GIMP (GNU Image Manipulation Program) image % file and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadXCFImage method is: % % image=ReadXCFImage(image_info) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) { char magick[14]; Image *image; int foundPropEnd = 0; MagickBooleanType status; MagickOffsetType offset; register ssize_t i; size_t image_type, length; ssize_t count; XCFDocInfo doc_info; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } count=ReadBlob(image,14,(unsigned char *) magick); if ((count != 14) || (LocaleNCompare((char *) magick,"gimp xcf",8) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); (void) ResetMagickMemory(&doc_info,0,sizeof(XCFDocInfo)); doc_info.width=ReadBlobMSBLong(image); doc_info.height=ReadBlobMSBLong(image); if ((doc_info.width > 262144) || (doc_info.height > 262144)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); doc_info.image_type=ReadBlobMSBLong(image); /* Initialize image attributes. */ image->columns=doc_info.width; image->rows=doc_info.height; image_type=doc_info.image_type; doc_info.file_size=GetBlobSize(image); image->compression=NoCompression; image->depth=8; status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); if (image_type == GIMP_RGB) SetImageColorspace(image,sRGBColorspace,exception); else if (image_type == GIMP_GRAY) SetImageColorspace(image,GRAYColorspace,exception); else if (image_type == GIMP_INDEXED) ThrowReaderException(CoderError,"ColormapTypeNotSupported"); (void) SetImageBackgroundColor(image,exception); (void) SetImageAlpha(image,OpaqueAlpha,exception); /* Read properties. */ while ((foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse)) { PropType prop_type = (PropType) ReadBlobMSBLong(image); size_t prop_size = ReadBlobMSBLong(image); switch (prop_type) { case PROP_END: foundPropEnd=1; break; case PROP_COLORMAP: { /* Cannot rely on prop_size here--the value is set incorrectly by some Gimp versions. */ size_t num_colours = ReadBlobMSBLong(image); if (DiscardBlobBytes(image,3*num_colours) == MagickFalse) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); /* if (info->file_version == 0) { gint i; g_message (_("XCF warning: version 0 of XCF file format\n" "did not save indexed colormaps correctly.\n" "Substituting grayscale map.")); info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); xcf_seek_pos (info, info->cp + gimage->num_cols); for (i = 0; i<gimage->num_cols; i++) { gimage->cmap[i*3+0] = i; gimage->cmap[i*3+1] = i; gimage->cmap[i*3+2] = i; } } else { info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); info->cp += xcf_read_int8 (info->fp, (guint8*) gimage->cmap, gimage->num_cols*3); } */ break; } case PROP_COMPRESSION: { doc_info.compression = ReadBlobByte(image); if ((doc_info.compression != COMPRESS_NONE) && (doc_info.compression != COMPRESS_RLE) && (doc_info.compression != COMPRESS_ZLIB) && (doc_info.compression != COMPRESS_FRACTAL)) ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression"); } break; case PROP_GUIDES: { /* just skip it - we don't care about guides */ if (DiscardBlobBytes(image,prop_size) == MagickFalse) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); } break; case PROP_RESOLUTION: { /* float xres = (float) */ (void) ReadBlobMSBLong(image); /* float yres = (float) */ (void) ReadBlobMSBLong(image); /* if (xres < GIMP_MIN_RESOLUTION || xres > GIMP_MAX_RESOLUTION || yres < GIMP_MIN_RESOLUTION || yres > GIMP_MAX_RESOLUTION) { g_message ("Warning, resolution out of range in XCF file"); xres = gimage->gimp->config->default_xresolution; yres = gimage->gimp->config->default_yresolution; } */ /* BOGUS: we don't write these yet because we aren't reading them properly yet :( image->resolution.x = xres; image->resolution.y = yres; */ } break; case PROP_TATTOO: { /* we need to read it, even if we ignore it */ /*size_t tattoo_state = */ (void) ReadBlobMSBLong(image); } break; case PROP_PARASITES: { /* BOGUS: we may need these for IPTC stuff */ if (DiscardBlobBytes(image,prop_size) == MagickFalse) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); /* gssize_t base = info->cp; GimpParasite *p; while (info->cp - base < prop_size) { p = xcf_load_parasite (info); gimp_image_parasite_attach (gimage, p); gimp_parasite_free (p); } if (info->cp - base != prop_size) g_message ("Error detected while loading an image's parasites"); */ } break; case PROP_UNIT: { /* BOGUS: ignore for now... */ /*size_t unit = */ (void) ReadBlobMSBLong(image); } break; case PROP_PATHS: { /* BOGUS: just skip it for now */ if (DiscardBlobBytes(image,prop_size) == MagickFalse) ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); /* PathList *paths = xcf_load_bzpaths (gimage, info); gimp_image_set_paths (gimage, paths); */ } break; case PROP_USER_UNIT: { char unit_string[1000]; /*BOGUS: ignored for now */ /*float factor = (float) */ (void) ReadBlobMSBLong(image); /* size_t digits = */ (void) ReadBlobMSBLong(image); for (i=0; i<5; i++) (void) ReadBlobStringWithLongSize(image, unit_string, sizeof(unit_string),exception); } break; default: { int buf[16]; ssize_t amount; /* read over it... */ while ((prop_size > 0) && (EOFBlob(image) == MagickFalse)) { amount=(ssize_t) MagickMin(16, prop_size); amount=(ssize_t) ReadBlob(image,(size_t) amount,(unsigned char *) &buf); if (!amount) ThrowReaderException(CorruptImageError,"CorruptImage"); prop_size -= (size_t) MagickMin(16,(size_t) amount); } } break; } } if (foundPropEnd == MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) { ; /* do nothing, were just pinging! */ } else { int current_layer = 0, foundAllLayers = MagickFalse, number_layers = 0; MagickOffsetType oldPos=TellBlob(image); XCFLayerInfo *layer_info; /* the read pointer */ do { ssize_t offset = ReadBlobMSBSignedLong(image); if (offset == 0) foundAllLayers=MagickTrue; else number_layers++; if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); break; } } while (foundAllLayers == MagickFalse); doc_info.number_layers=number_layers; offset=SeekBlob(image,oldPos,SEEK_SET); /* restore the position! */ if (offset < 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); /* allocate our array of layer info blocks */ length=(size_t) number_layers; layer_info=(XCFLayerInfo *) AcquireQuantumMemory(length, sizeof(*layer_info)); if (layer_info == (XCFLayerInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); (void) ResetMagickMemory(layer_info,0,number_layers*sizeof(XCFLayerInfo)); for ( ; ; ) { MagickBooleanType layer_ok; MagickOffsetType offset, saved_pos; /* read in the offset of the next layer */ offset=(MagickOffsetType) ReadBlobMSBLong(image); /* if the offset is 0 then we are at the end * of the layer list. */ if (offset == 0) break; /* save the current position as it is where the * next layer offset is stored. */ saved_pos=TellBlob(image); /* seek to the layer offset */ offset=SeekBlob(image,offset,SEEK_SET); /* read in the layer */ layer_ok=ReadOneLayer(image_info,image,&doc_info, &layer_info[current_layer],current_layer,exception); if (layer_ok == MagickFalse) { int j; for (j=0; j < current_layer; j++) layer_info[j].image=DestroyImage(layer_info[j].image); layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } /* restore the saved position so we'll be ready to * read the next offset. */ offset=SeekBlob(image, saved_pos, SEEK_SET); current_layer++; } #if 0 { /* NOTE: XCF layers are REVERSED from composite order! */ signed int j; for (j=number_layers-1; j>=0; j--) { /* BOGUS: need to consider layer blending modes!! */ if ( layer_info[j].visible ) { /* only visible ones, please! */ CompositeImage(image, OverCompositeOp, layer_info[j].image, layer_info[j].offset_x, layer_info[j].offset_y ); layer_info[j].image =DestroyImage( layer_info[j].image ); /* If we do this, we'll get REAL gray images! */ if ( image_type == GIMP_GRAY ) { QuantizeInfo qi; GetQuantizeInfo(&qi); qi.colorspace = GRAYColorspace; QuantizeImage( &qi, layer_info[j].image ); } } } } #else { /* NOTE: XCF layers are REVERSED from composite order! */ ssize_t j; /* now reverse the order of the layers as they are put into subimages */ for (j=(ssize_t) number_layers-1; j >= 0; j--) AppendImageToList(&image,layer_info[j].image); } #endif layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info); #if 0 /* BOGUS: do we need the channels?? */ while (MagickTrue) { /* read in the offset of the next channel */ info->cp += xcf_read_int32 (info->fp, &offset, 1); /* if the offset is 0 then we are at the end * of the channel list. */ if (offset == 0) break; /* save the current position as it is where the * next channel offset is stored. */ saved_pos = info->cp; /* seek to the channel offset */ xcf_seek_pos (info, offset); /* read in the layer */ channel = xcf_load_channel (info, gimage); if (channel == 0) goto error; num_successful_elements++; /* add the channel to the image if its not the selection */ if (channel != gimage->selection_mask) gimp_image_add_channel (gimage, channel, -1); /* restore the saved position so we'll be ready to * read the next offset. */ xcf_seek_pos (info, saved_pos); } #endif } (void) CloseBlob(image); DestroyImage(RemoveFirstImageFromList(&image)); if (image_type == GIMP_GRAY) image->type=GrayscaleType; return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d V I D I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadVIDImage reads one of more images and creates a Visual Image % Directory file. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadVIDImage method is: % % Image *ReadVIDImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadVIDImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define ClientName "montage" char **filelist, *label; Image *image, *images, *montage_image, *next_image, *thumbnail_image; ImageInfo *read_info; int number_files; MagickBooleanType status; MontageInfo *montage_info; RectangleInfo geometry; register ssize_t i; /* Expand the filename. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); filelist=(char **) AcquireAlignedMemory(1,sizeof(*filelist)); if (filelist == (char **) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); filelist[0]=ConstantString(image_info->filename); number_files=1; status=ExpandFilenames(&number_files,&filelist); if ((status == MagickFalse) || (number_files == 0)) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); image=DestroyImage(image); /* Read each image and convert them to a tile. */ images=NewImageList(); read_info=CloneImageInfo(image_info); SetImageInfoBlob(read_info,(void *) NULL,0); (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL, (void *) NULL); if (read_info->size == (char *) NULL) (void) CloneString(&read_info->size,DefaultTileGeometry); for (i=0; i < (ssize_t) number_files; i++) { if (image_info->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(),"name: %s", filelist[i]); (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent); filelist[i]=DestroyString(filelist[i]); *read_info->magick='\0'; next_image=ReadImage(read_info,exception); CatchException(exception); if (next_image == (Image *) NULL) break; label=InterpretImageProperties(image_info,next_image,DefaultTileLabel); (void) SetImageProperty(next_image,"label",label); label=DestroyString(label); if (image_info->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "geometry: %.20gx%.20g",(double) next_image->columns,(double) next_image->rows); SetGeometry(next_image,&geometry); (void) ParseMetaGeometry(read_info->size,&geometry.x,&geometry.y, &geometry.width,&geometry.height); thumbnail_image=ThumbnailImage(next_image,geometry.width,geometry.height, exception); if (thumbnail_image != (Image *) NULL) { next_image=DestroyImage(next_image); next_image=thumbnail_image; } if (image_info->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "thumbnail geometry: %.20gx%.20g",(double) next_image->columns,(double) next_image->rows); AppendImageToList(&images,next_image); status=SetImageProgress(images,LoadImagesTag,i,number_files); if (status == MagickFalse) break; } read_info=DestroyImageInfo(read_info); filelist=(char **) RelinquishMagickMemory(filelist); if (images == (Image *) NULL) ThrowReaderException(CorruptImageError, "ImageFileDoesNotContainAnyImageData"); /* Create the visual image directory. */ montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL); if (image_info->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(),"creating montage"); montage_image=MontageImageList(image_info,montage_info, GetFirstImageInList(images),exception); montage_info=DestroyMontageInfo(montage_info); images=DestroyImageList(images); return(montage_image); }
MagickExport Image *ChannelFxImage(const Image *image,const char *expression, ExceptionInfo *exception) { #define ChannelFxImageTag "ChannelFx/Image" ChannelFx channel_op; ChannelType channel_mask; char token[MaxTextExtent]; const char *p; const Image *source_image; double pixel; Image *destination_image; MagickBooleanType status; PixelChannel source_channel, destination_channel; ssize_t channels; 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); source_image=image; destination_image=CloneImage(source_image,0,0,MagickTrue,exception); if (destination_image == (Image *) NULL) return((Image *) NULL); if (expression == (const char *) NULL) return(destination_image); destination_channel=RedPixelChannel; channel_mask=UndefinedChannel; pixel=0.0; p=(char *) expression; GetMagickToken(p,&p,token); channel_op=ExtractChannelOp; for (channels=0; *token != '\0'; ) { ssize_t i; /* Interpret channel expression. */ switch (*token) { case ',': { GetMagickToken(p,&p,token); break; } case '|': { if (GetNextImageInList(source_image) != (Image *) NULL) source_image=GetNextImageInList(source_image); else source_image=GetFirstImageInList(source_image); GetMagickToken(p,&p,token); break; } case ';': { Image *canvas; SetPixelChannelMask(destination_image,channel_mask); if ((channel_op == ExtractChannelOp) && (channels == 1)) (void) SetImageColorspace(destination_image,GRAYColorspace,exception); status=SetImageStorageClass(destination_image,DirectClass,exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); return(destination_image); } canvas=CloneImage(source_image,0,0,MagickTrue,exception); if (canvas == (Image *) NULL) { destination_image=DestroyImageList(destination_image); return(destination_image); } AppendImageToList(&destination_image,canvas); destination_image=GetLastImageInList(destination_image); GetMagickToken(p,&p,token); channels=0; destination_channel=RedPixelChannel; channel_mask=UndefinedChannel; break; } default: break; } i=ParsePixelChannelOption(token); if (i < 0) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnrecognizedChannelType","`%s'",token); destination_image=DestroyImageList(destination_image); return(destination_image); } source_channel=(PixelChannel) i; channel_op=ExtractChannelOp; GetMagickToken(p,&p,token); if (*token == '<') { channel_op=ExchangeChannelOp; GetMagickToken(p,&p,token); } if (*token == '=') { if (channel_op != ExchangeChannelOp) channel_op=AssignChannelOp; GetMagickToken(p,&p,token); } if (*token == '>') { if (channel_op != ExchangeChannelOp) channel_op=TransferChannelOp; GetMagickToken(p,&p,token); } switch (channel_op) { case AssignChannelOp: { pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0); GetMagickToken(p,&p,token); break; } case ExchangeChannelOp: case TransferChannelOp: { i=ParsePixelChannelOption(token); if (i < 0) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnrecognizedChannelType","`%s'",token); destination_image=DestroyImageList(destination_image); return(destination_image); } destination_channel=(PixelChannel) i; switch (destination_channel) { case RedPixelChannel: case GreenPixelChannel: case BluePixelChannel: case BlackPixelChannel: case IndexPixelChannel: break; case AlphaPixelChannel: { destination_image->alpha_trait=BlendPixelTrait; break; } case ReadMaskPixelChannel: { destination_image->read_mask=MagickTrue; break; } case WriteMaskPixelChannel: { destination_image->write_mask=MagickTrue; break; } case MetaPixelChannel: default: { (void) SetPixelMetaChannels(destination_image,(size_t) (i- GetPixelChannels(destination_image)+1),exception); break; } } channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token)); if (((channels >= 1) || (destination_channel >= 1)) && (IsGrayColorspace(destination_image->colorspace) != MagickFalse)) (void) SetImageColorspace(destination_image,sRGBColorspace,exception); GetMagickToken(p,&p,token); break; } default: break; } status=ChannelImage(destination_image,destination_channel,channel_op, source_image,source_channel,ClampToQuantum(pixel),exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); break; } channels++; if (channel_op == ExchangeChannelOp) { status=ChannelImage(destination_image,source_channel,channel_op, source_image,destination_channel,ClampToQuantum(pixel),exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); break; } channels++; } switch (channel_op) { case ExtractChannelOp: { channel_mask=(ChannelType) (channel_mask | (1 << destination_channel)); destination_channel=(PixelChannel) (destination_channel+1); break; } default: break; } status=SetImageProgress(source_image,ChannelFxImageTag,p-expression, strlen(expression)); if (status == MagickFalse) break; } SetPixelChannelMask(destination_image,channel_mask); if ((channel_op == ExtractChannelOp) && (channels == 1)) (void) SetImageColorspace(destination_image,GRAYColorspace,exception); status=SetImageStorageClass(destination_image,DirectClass,exception); if (status == MagickFalse) { destination_image=GetLastImageInList(destination_image); return((Image *) NULL); } return(GetFirstImageInList(destination_image)); }
// GP: mode = -1 will be automatically guessed from the file SEXP lib_readImages (SEXP files, SEXP mode) { SEXP res; int _mode, i, nappends; Image * image, * images; ImageInfo * image_info; ExceptionInfo exception; const char * file; ImageType it; if ( LENGTH(files) < 1 ) error ( "please supply at least one file name or URL" ); _mode = INTEGER (mode)[0]; if ( _mode < -1 || _mode > MODE_MAX) error ( "requested mode is not supported" ); // Special call for reading Cellomics image if (LENGTH(files)==1) { file = CHAR(STRING_ELT(files, 0)); i = strlen(file); if (i>4 && (strncmp(&file[i-4], ".c01", 4)==0 || strncmp(&file[i-4], ".C01", 4)==0)) { return (readCellomics(file)); } } image_info = (ImageInfo *) NULL; /* images loaded into image and moved into this list */ images = NewImageList (); GetExceptionInfo (&exception); image_info = CloneImageInfo ( (ImageInfo *)NULL ); nappends = 0; for ( i = 0; i < LENGTH (files); i++ ) { if ( LENGTH (files) > 1 ) file = CHAR ( STRING_ELT(files, i) ); else file = CHAR ( asChar(files) ); strcpy (image_info->filename, file); // Prevent an ImageMagick bug when file is an empty string or NULL if (file==NULL) image=NULL; else if (strlen(file)==0) image=NULL; else { image = ReadImage (image_info, &exception); CatchException (&exception); } if ( image == (Image *)NULL ) { warning ("requested image not found or could not be loaded" ); continue; } // Automatic color mode guess if (_mode==-1) { it = GetImageType(image,&exception); // Rprintf("it=%d G=%d P=%d PM=%d\n",it, GrayscaleType, PaletteType, PaletteMatteType); if (it==BilevelType || it==GrayscaleType || it==GrayscaleMatteType) _mode=MODE_GRAYSCALE; else _mode=MODE_COLOR; } /* do not destroy image here */ AppendImageToList (&images, image); if ( nappends == 0 ) { /* set all attributes from the first image */ strcpy (images->filename, image->filename); images->compression = image->compression; images->x_resolution = image->x_resolution; images->y_resolution = image->y_resolution; } nappends++; } /* do not update image properties here because if no image was added to the list it will cause segfault, or use GetImageListLength first to check size */ image_info = DestroyImageInfo (image_info); /* convert image list into R object */ res = PROTECT(magick2SEXP (images, _mode)); images = DestroyImageList (images); DestroyExceptionInfo(&exception); UNPROTECT(1); return res; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d M P E G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadMPEGImage() reads an binary file in the MPEG video stream format % and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. This method differs from % the other decoder methods in that only the Photoshop resource (MPEG) % information is useful in the returned image. % % The format of the ReadMPEGImage method is: % % Image *ReadMPEGImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: The image info. % % o exception: return any errors or warnings in this structure. % % */ static Image *ReadMPEGImage(const ImageInfo *image_info, ExceptionInfo *exception) { Image *image, *images; ImageInfo *read_info; MagickBooleanType status; register long i; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AllocateImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } CloseBlob(image); DestroyImageList(image); /* Convert MPEG to PPM with delegate. */ image=AllocateImage(image_info); read_info=CloneImageInfo(image_info); (void) InvokeDelegate(read_info,image,"mpeg-decode",(char *) NULL,exception); image=DestroyImage(image); /* Read PPM files. */ images=NewImageList(); for (i=(long) read_info->scene; ; i++) { (void) FormatMagickString(read_info->filename,MaxTextExtent, "%s%ld.ppm",read_info->unique,i); if (IsAccessible(read_info->filename) == MagickFalse) break; image=ReadImage(read_info,exception); if (image == (Image *) NULL) break; (void) strcpy(image->magick,image_info->magick); image->scene=(unsigned long) i; AppendImageToList(&images,image); if (read_info->number_scenes != 0) if (i >= (long) (read_info->scene+read_info->number_scenes-1)) break; } /* Free resources. */ for (i=0; ; i++) { (void) FormatMagickString(read_info->filename,MaxTextExtent, "%s%ld.ppm",read_info->unique,i); if (IsAccessible(read_info->filename) == MagickFalse) break; (void) remove(read_info->filename); } read_info=DestroyImageInfo(read_info); return(images); }