From ab272ac4f115daf25c032de9dbb49a399eebe49b Mon Sep 17 00:00:00 2001 From: cristy Date: Sun, 4 Mar 2012 22:08:07 +0000 Subject: [PATCH] --- MagickCore/channel.c | 205 ++++++++++++++++++++++++++++++++++++------- MagickCore/image.c | 2 +- coders/caption.c | 69 +++++++-------- 3 files changed, 206 insertions(+), 70 deletions(-) diff --git a/MagickCore/channel.c b/MagickCore/channel.c index 4fd75d6c3..d790821f3 100644 --- a/MagickCore/channel.c +++ b/MagickCore/channel.c @@ -44,7 +44,10 @@ #include "MagickCore/image.h" #include "MagickCore/list.h" #include "MagickCore/log.h" +#include "MagickCore/monitor.h" +#include "MagickCore/monitor-private.h" #include "MagickCore/option.h" +#include "MagickCore/pixel-accessor.h" #include "MagickCore/token.h" #include "MagickCore/utility.h" #include "MagickCore/version.h" @@ -61,15 +64,28 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ChannelOperationImage() applies a channel expression to the specified image. +% The expression consists of one or more channels, either mnemonic or numeric +% (e.g. red, 1), separated by certain operation symbols as follows: +% +% <=> exchange two channels (e.g. red<=>blue) +% => transfer a channel to another (e.g. red=>green) +% , separate channel operations (e.g. red, green) +% | read channels from next input image (e.g. red | green) +% ; write channels to next output image (e.g. red; green; blue) +% +% A channel without a operation symbol implies extract. For example, to create +% 3 grayscale images from the red, green, and blue channels of an image, use: +% +% -channel-ops "red; green; blue" % % The format of the ChannelOperationImage method is: % -% Image *ChannelOperationImage(const Image *images, +% Image *ChannelOperationImage(const Image *image, % const char *expression,ExceptionInfo *exception) % % A description of each parameter follows: % -% o images: the images. +% o image: the image. % % o expression: A channel expression. % @@ -84,16 +100,97 @@ typedef enum TransferChannelOp } ChannelOperation; -static MagickBooleanType ChannelImage(Image *channel_image,const Image *image, - const ChannelOperation channel_op,const PixelChannel p_channel, - const PixelChannel q_channel,ExceptionInfo *exception) +static inline size_t MagickMin(const size_t x,const size_t y) { - return(MagickTrue); + if (x < y) + return(x); + return(y); } -MagickExport Image *ChannelOperationImage(const Image *images, +static MagickBooleanType ChannelImage(Image *destination_image, + const Image *source_image,const ChannelOperation channel_op, + const PixelChannel source_channel,const PixelChannel destination_channel, + ExceptionInfo *exception) +{ + CacheView + *source_view, + *destination_view; + + MagickBooleanType + status; + + size_t + height; + + ssize_t + y; + + status=MagickTrue; + source_view=AcquireCacheView(source_image); + destination_view=AcquireCacheView(destination_image); + height=MagickMin(source_image->rows,destination_image->rows); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static) shared(status) +#endif + for (y=0; y < (ssize_t) height; y++) + { + register const Quantum + *restrict p; + + register Quantum + *restrict q; + + register ssize_t + x; + + size_t + width; + + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1, + exception); + q=QueueCacheViewAuthenticPixels(destination_view,0,y, + destination_image->columns,1,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + { + status=MagickFalse; + continue; + } + width=MagickMin(source_image->columns,destination_image->columns); + for (x=0; x < (ssize_t) width; x++) + { + PixelTrait + destination_traits, + source_traits; + + ssize_t + offset; + + source_traits=GetPixelChannelMapTraits(source_image,source_channel); + destination_traits=GetPixelChannelMapTraits(destination_image, + destination_channel); + if ((source_traits == UndefinedPixelTrait) || + (destination_traits == UndefinedPixelTrait)) + continue; + offset=GetPixelChannelMapOffset(source_image,source_channel); + SetPixelChannel(destination_image,destination_channel,p[offset],q); + p+=GetPixelChannels(source_image); + q+=GetPixelChannels(destination_image); + } + if (SyncCacheViewAuthenticPixels(destination_view,exception) == MagickFalse) + status=MagickFalse; + } + destination_view=DestroyCacheView(destination_view); + source_view=DestroyCacheView(source_view); + return(status); +} + +MagickExport Image *ChannelOperationImage(const Image *image, const char *expression,ExceptionInfo *exception) { +#define ChannelOperationImageTag "ChannelOperation/Image" + char token[MaxTextExtent]; @@ -103,22 +200,40 @@ MagickExport Image *ChannelOperationImage(const Image *images, const char *p; + const Image + *source_image; + Image - *channel_images; + *destination_image; PixelChannel - p_channel, - q_channel; - - assert(images != (Image *) NULL); - assert(images->signature == MagickSignature); - if (images->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); - channel_images=CloneImage(images,images->columns,images->columns,MagickTrue, - exception); + 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 (SetImageBackgroundColor(destination_image,exception) == MagickFalse) + { + destination_image=GetLastImageInList(destination_image); + return((Image *) NULL); + } + if (expression == (const char *) NULL) + return(destination_image); + destination_channel=RedPixelChannel; p=(char *) expression; GetMagickToken(p,&p,token); - for (q_channel=RedPixelChannel; *p != '\0'; ) + for (channels=0; *p != '\0'; ) { MagickBooleanType status; @@ -131,33 +246,50 @@ MagickExport Image *ChannelOperationImage(const Image *images, */ if (*token == ',') { - q_channel=(PixelChannel) ((ssize_t) q_channel+1); + destination_channel=(PixelChannel) ((ssize_t) destination_channel+1); GetMagickToken(p,&p,token); } if (*token == '|') { - if (GetNextImageInList(images) != (Image *) NULL) - images=GetNextImageInList(images); + if (GetNextImageInList(source_image) != (Image *) NULL) + source_image=GetNextImageInList(source_image); else - images=GetFirstImageInList(images); + source_image=GetFirstImageInList(source_image); GetMagickToken(p,&p,token); } if (*token == ';') { - AppendImageToList(&channel_images,CloneImage(images, - channel_images->columns,channel_images->rows,MagickTrue,exception)); - channel_images=GetLastImageInList(channel_images); + Image + *canvas; + + if (channels == 1) + destination_image->colorspace=GRAYColorspace; + canvas=CloneImage(source_image,0,0,MagickTrue,exception); + if (canvas == (Image *) NULL) + { + destination_image=GetLastImageInList(destination_image); + return((Image *) NULL); + } + AppendImageToList(&destination_image,canvas); + destination_image=GetLastImageInList(destination_image); + if (SetImageBackgroundColor(destination_image,exception) == MagickFalse) + { + destination_image=GetLastImageInList(destination_image); + return((Image *) NULL); + } GetMagickToken(p,&p,token); + channels=0; + destination_channel=RedPixelChannel; } i=ParsePixelChannelOption(token); if (i < 0) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnableToParseExpression","`%s'",p); - channel_images=DestroyImageList(channel_images); + destination_image=DestroyImageList(destination_image); break; } - p_channel=(PixelChannel) i; + source_channel=(PixelChannel) i; channel_op=ExtractChannelOp; GetMagickToken(p,&p,token); if (*token == '<') @@ -180,18 +312,25 @@ MagickExport Image *ChannelOperationImage(const Image *images, { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnableToParseExpression","`%s'",p); - channel_images=DestroyImageList(channel_images); + destination_image=DestroyImageList(destination_image); break; } - q_channel=(PixelChannel) i; + destination_channel=(PixelChannel) i; } - status=ChannelImage(channel_images,images,channel_op,p_channel,q_channel, - exception); + status=ChannelImage(destination_image,source_image,channel_op, + source_channel,destination_channel,exception); if (status == MagickFalse) { - channel_images=DestroyImageList(channel_images); + destination_image=DestroyImageList(destination_image); break; } + channels++; + status=SetImageProgress(source_image,ChannelOperationImageTag,p-expression, + strlen(expression)); + if (status == MagickFalse) + break; } - return(channel_images); + if (channels == 1) + destination_image->colorspace=GRAYColorspace; + return(destination_image); } diff --git a/MagickCore/image.c b/MagickCore/image.c index 910a1be53..b6de468e4 100644 --- a/MagickCore/image.c +++ b/MagickCore/image.c @@ -2244,7 +2244,7 @@ MagickExport Image *SeparateImage(const Image *image, y; /* - Initialize spread image attributes. + Initialize seaprate image attributes. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); diff --git a/coders/caption.c b/coders/caption.c index 33a3830a2..5e0063900 100644 --- a/coders/caption.c +++ b/coders/caption.c @@ -109,8 +109,8 @@ static void PangoSubstitute(FcPattern *pattern,void *context) FcPatternAddBool(pattern,FC_AUTOHINT,LocaleCompare(option,"auto") == 0); } -static Image *ReadCAPTIONImage(const ImageInfo *image_info, - ExceptionInfo *exception) +static MagickBooleanType PangoImage(const ImageInfo *image_info,Image *image, + const DrawInfo *draw_info,ExceptionInfo *exception) { char *caption, @@ -119,15 +119,9 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, const char *option; - DrawInfo - *draw_info; - FT_Bitmap *canvas; - Image - *image; - PangoAlignment align; @@ -164,18 +158,6 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, ssize_t y; - /* - Initialize Image structure. - */ - 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); - (void) ResetImagePage(image,"0x0+0+0"); /* Get context. */ @@ -189,7 +171,6 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, option=GetImageOption(image_info,"caption:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); - draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) @@ -263,7 +244,8 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, pango_layout_set_alignment(layout,align); description=pango_font_description_from_string(draw_info->font == (char *) NULL ? "helvetica" : draw_info->font); - pango_font_description_set_size(description,PANGO_SCALE*draw_info->pointsize); + pango_font_description_set_size(description,(int) (0.9*PANGO_SCALE* + draw_info->pointsize+0.5)); pango_layout_set_font_description(layout,description); pango_font_description_free(description); option=GetImageOption(image_info,"filename"); @@ -318,10 +300,8 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, */ canvas=(FT_Bitmap *) AcquireMagickMemory(sizeof(*canvas)); if (canvas == (FT_Bitmap *) NULL) - { - draw_info=DestroyDrawInfo(draw_info); - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - } + ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", + image->filename); canvas->width=image->columns; canvas->pitch=(canvas->width+3) & ~3; canvas->rows=image->rows; @@ -329,9 +309,9 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, canvas->rows*sizeof(*canvas->buffer)); if (canvas->buffer == (unsigned char *) NULL) { - draw_info=DestroyDrawInfo(draw_info); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", + image->filename); } canvas->num_grays=256; canvas->pixel_mode=ft_pixel_mode_grays; @@ -344,12 +324,11 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, image->rows+=2*page.y; if (SetImageBackgroundColor(image,exception) == MagickFalse) { - draw_info=DestroyDrawInfo(draw_info); canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); caption=DestroyString(caption); image=DestroyImageList(image); - return((Image *) NULL); + return(MagickFalse); } GetPixelInfo(image,&fill_color); p=canvas->buffer; @@ -383,13 +362,13 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, /* Relinquish resources. */ - draw_info=DestroyDrawInfo(draw_info); canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); caption=DestroyString(caption); - return(GetFirstImageInList(image)); + return(MagickTrue); } -#else +#endif + static Image *ReadCAPTIONImage(const ImageInfo *image_info, ExceptionInfo *exception) { @@ -399,7 +378,8 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, *property; const char - *gravity; + *gravity, + *option; DrawInfo *draw_info; @@ -439,6 +419,15 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, */ property=InterpretImageProperties(image_info,image,image_info->filename, exception); + option=GetImageOption(image_info,"filename"); + if (option == (const char *) NULL) + property=InterpretImageProperties(image_info,image,image_info->filename, + exception); + else + if (LocaleNCompare(option,"caption:",8) == 0) + property=InterpretImageProperties(image_info,image,option+8,exception); + else + property=InterpretImageProperties(image_info,image,option,exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); @@ -528,12 +517,20 @@ static Image *ReadCAPTIONImage(const ImageInfo *image_info, metrics.ascent+draw_info->stroke_width/2.0); draw_info->geometry=AcquireString(geometry); } - (void) AnnotateImage(image,draw_info,exception); +#if defined(MAGICKCORE_PANGOFT2_DELEGATE) + status=PangoImage(image_info,image,draw_info,exception); +#else + status=AnnotateImage(image,draw_info,exception); +#endif draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); + if (status == MagickFalse) + { + image=DestroyImageList(image); + return((Image *) NULL); + } return(GetFirstImageInList(image)); } -#endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- 2.40.0