]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Sun, 4 Mar 2012 22:08:07 +0000 (22:08 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Sun, 4 Mar 2012 22:08:07 +0000 (22:08 +0000)
MagickCore/channel.c
MagickCore/image.c
coders/caption.c

index 4fd75d6c31c5ca378ec1d21dd1fff3623ca7d02e..d790821f366aa31f8fce6c121b0a787b7f21d126 100644 (file)
 #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"
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  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);
 }
index 910a1be53aa9936f382e7abe5396a5263702c4a3..b6de468e4b5e9f5c2db5471fb7f57a1aad8e0749 100644 (file)
@@ -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);
index 33a3830a2e540277b27cbc269bad7209024b7104..5e00639007ac5236291b030fdfa3ca2979866bb3 100644 (file)
@@ -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
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%