]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/paint.c
(no commit message)
[imagemagick] / MagickCore / paint.c
index 05695c99614a2df76b8e662e41beb7375abcf686..75dc1259197ed5823328ea82e77e2eb15877ed5b 100644 (file)
 %                        Methods to Paint on an Image                         %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1998                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -40,6 +40,7 @@
  Include declarations.
 */
 #include "MagickCore/studio.h"
+#include "MagickCore/channel.h"
 #include "MagickCore/color.h"
 #include "MagickCore/color-private.h"
 #include "MagickCore/colorspace-private.h"
@@ -110,7 +111,7 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
   const ssize_t y_offset,const MagickBooleanType invert,
   ExceptionInfo *exception)
 {
-#define MaxStacksize  (1UL << 15)
+#define MaxStacksize  131072UL
 #define PushSegmentStack(up,left,right,delta) \
 { \
   if (s >= (segment_stack+MaxStacksize)) \
@@ -139,6 +140,9 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
     skip,
     status;
 
+  MemoryInfo
+    *segment_info;
+
   PixelInfo
     fill_color,
     pixel;
@@ -173,8 +177,9 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) TransformImageColorspace(image,sRGBColorspace,exception);
-  if ((image->matte == MagickFalse) && (draw_info->fill.matte != MagickFalse))
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
+  if ((image->alpha_trait != BlendPixelTrait) &&
+      (draw_info->fill.alpha_trait == BlendPixelTrait))
     (void) SetImageAlpha(image,OpaqueAlpha,exception);
   /*
     Set floodfill state.
@@ -183,16 +188,19 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
     exception);
   if (floodplane_image == (Image *) NULL)
     return(MagickFalse);
-  SetImageColorspace(floodplane_image,GRAYColorspace,exception);
-  (void) EvaluateImage(floodplane_image,SetEvaluateOperator,0.0,exception);
-  segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize,
-    sizeof(*segment_stack));
-  if (segment_stack == (SegmentInfo *) NULL)
+  floodplane_image->alpha_trait=UndefinedPixelTrait;
+  floodplane_image->colorspace=GRAYColorspace;
+  (void) QueryColorCompliance("#000",AllCompliance,
+    &floodplane_image->background_color,exception);
+  (void) SetImageBackgroundColor(floodplane_image,exception);
+  segment_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack));
+  if (segment_info == (MemoryInfo *) NULL)
     {
       floodplane_image=DestroyImage(floodplane_image);
       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
         image->filename);
     }
+  segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info);
   /*
     Push initial segment on stack.
   */
@@ -344,7 +352,7 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
   }
   floodplane_view=DestroyCacheView(floodplane_view);
   image_view=DestroyCacheView(image_view);
-  segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack);
+  segment_info=RelinquishVirtualMemory(segment_info);
   floodplane_image=DestroyImage(floodplane_image);
   return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
 }
@@ -452,13 +460,9 @@ MagickExport MagickBooleanType GradientImage(Image *image,
   /*
     Draw a gradient on the image.
   */
+  (void) SetImageColorspace(image,start_color->colorspace,exception);
   status=DrawGradientImage(image,draw_info,exception);
   draw_info=DestroyDrawInfo(draw_info);
-  if ((start_color->matte == MagickFalse) && (stop_color->matte == MagickFalse))
-    image->matte=MagickFalse;
-  if ((IsPixelInfoGray(start_color) != MagickFalse) &&
-      (IsPixelInfoGray(stop_color) != MagickFalse))
-    image->type=GrayscaleType;
   return(status);
 }
 \f
@@ -516,7 +520,7 @@ static size_t **AcquireHistogramThreadSet(const size_t count)
     **histogram,
     number_threads;
 
-  number_threads=GetOpenMPMaximumThreads();
+  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
   histogram=(size_t **) AcquireQuantumMemory(number_threads,sizeof(*histogram));
   if (histogram == (size_t **) NULL)
     return((size_t **) NULL);
@@ -541,6 +545,7 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
     *paint_view;
 
   Image
+    *linear_image,
     *paint_image;
 
   MagickBooleanType
@@ -567,17 +572,26 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
   width=GetOptimalKernelWidth2D(radius,sigma);
+  linear_image=CloneImage(image,0,0,MagickTrue,exception);
   paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
-  if (paint_image == (Image *) NULL)
-    return((Image *) NULL);
+  if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL))
+    {
+      if (linear_image != (Image *) NULL)
+        linear_image=DestroyImage(linear_image);
+      if (paint_image != (Image *) NULL)
+        linear_image=DestroyImage(paint_image);
+      return((Image *) NULL);
+    }
   if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse)
     {
+      linear_image=DestroyImage(linear_image);
       paint_image=DestroyImage(paint_image);
       return((Image *) NULL);
     }
   histograms=AcquireHistogramThreadSet(NumberPaintBins);
   if (histograms == (size_t **) NULL)
     {
+      linear_image=DestroyImage(linear_image);
       paint_image=DestroyImage(paint_image);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
     }
@@ -586,15 +600,15 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
   */
   status=MagickTrue;
   progress=0;
-  center=(ssize_t) GetPixelChannels(image)*(image->columns+width)*(width/2L)+
-    GetPixelChannels(image)*(width/2L);
-  image_view=AcquireVirtualCacheView(image,exception);
+  center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)*
+    (width/2L)+GetPixelChannels(linear_image)*(width/2L);
+  image_view=AcquireVirtualCacheView(linear_image,exception);
   paint_view=AcquireAuthenticCacheView(paint_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
-    dynamic_number_threads(image->columns,image->rows,1)
+    magick_threads(linear_image,paint_image,linear_image->rows,1)
 #endif
-  for (y=0; y < (ssize_t) image->rows; y++)
+  for (y=0; y < (ssize_t) linear_image->rows; y++)
   {
     register const Quantum
       *restrict p;
@@ -611,7 +625,7 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
     if (status == MagickFalse)
       continue;
     p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
-      (width/2L),image->columns+width,width,exception);
+      (width/2L),linear_image->columns+width,width,exception);
     q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
@@ -620,7 +634,7 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
         continue;
       }
     histogram=histograms[GetOpenMPThreadId()];
-    for (x=0; x < (ssize_t) image->columns; x++)
+    for (x=0; x < (ssize_t) linear_image->columns; x++)
     {
       register ssize_t
         i,
@@ -646,8 +660,8 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
       {
         for (u=0; u < (ssize_t) width; u++)
         {
-          n=(ssize_t) ScaleQuantumToChar(GetPixelIntensity(image,p+
-            GetPixelChannels(image)*(u+k)));
+          n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
+            linear_image,p+GetPixelChannels(linear_image)*(u+k))));
           histogram[n]++;
           if (histogram[n] > count)
             {
@@ -655,42 +669,31 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
               count=histogram[n];
             }
         }
-        k+=(ssize_t) (image->columns+width);
+        k+=(ssize_t) (linear_image->columns+width);
       }
-      if (GetPixelMask(image,p) != 0)
-        {
-          p+=GetPixelChannels(image);
-          q+=GetPixelChannels(paint_image);
-          continue;
-        }
-      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          paint_traits,
-          traits;
-
-        channel=GetPixelChannelMapChannel(image,i);
-        traits=GetPixelChannelMapTraits(image,channel);
-        paint_traits=GetPixelChannelMapTraits(paint_image,channel);
+        PixelChannel channel=GetPixelChannelChannel(linear_image,i);
+        PixelTrait traits=GetPixelChannelTraits(linear_image,channel);
+        PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (paint_traits == UndefinedPixelTrait))
           continue;
-        if ((paint_traits & CopyPixelTrait) != 0)
+        if (((paint_traits & CopyPixelTrait) != 0) ||
+            (GetPixelReadMask(linear_image,p) == 0))
           {
             SetPixelChannel(paint_image,channel,p[center+i],q);
             continue;
           }
-        SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(image)+i],q);
+        SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+
+          i],q);
       }
-      p+=GetPixelChannels(image);
+      p+=GetPixelChannels(linear_image);
       q+=GetPixelChannels(paint_image);
     }
     if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
       status=MagickFalse;
-    if (image->progress_monitor != (MagickProgressMonitor) NULL)
+    if (linear_image->progress_monitor != (MagickProgressMonitor) NULL)
       {
         MagickBooleanType
           proceed;
@@ -698,7 +701,8 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
         #pragma omp critical (MagickCore_OilPaintImage)
 #endif
-        proceed=SetImageProgress(image,OilPaintImageTag,progress++,image->rows);
+        proceed=SetImageProgress(linear_image,OilPaintImageTag,progress++,
+          linear_image->rows);
         if (proceed == MagickFalse)
           status=MagickFalse;
       }
@@ -706,6 +710,7 @@ MagickExport Image *OilPaintImage(const Image *image,const double radius,
   paint_view=DestroyCacheView(paint_view);
   image_view=DestroyCacheView(image_view);
   histograms=DestroyHistogramThreadSet(histograms);
+  linear_image=DestroyImage(linear_image);
   if (status == MagickFalse)
     paint_image=DestroyImage(paint_image);
   return(paint_image);
@@ -780,9 +785,10 @@ MagickExport MagickBooleanType OpaquePaintImage(Image *image,
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
-      (IsPixelInfoGray(fill) != MagickFalse))
-    (void) TransformImageColorspace(image,sRGBColorspace,exception);
-  if ((fill->matte != MagickFalse) && (image->matte == MagickFalse))
+      (IsPixelInfoGray(fill) == MagickFalse))
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
+  if ((fill->alpha_trait == BlendPixelTrait) &&
+      (image->alpha_trait != BlendPixelTrait))
     (void) SetImageAlpha(image,OpaqueAlpha,exception);
   /*
     Make image color opaque.
@@ -793,7 +799,7 @@ MagickExport MagickBooleanType OpaquePaintImage(Image *image,
   image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
-    dynamic_number_threads(image->columns,image->rows,1)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -909,7 +915,7 @@ MagickExport MagickBooleanType TransparentPaintImage(Image *image,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait != BlendPixelTrait)
     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
   /*
     Make image color transparent.
@@ -920,7 +926,7 @@ MagickExport MagickBooleanType TransparentPaintImage(Image *image,
   image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
-    dynamic_number_threads(image->columns,image->rows,1)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1037,7 +1043,7 @@ MagickExport MagickBooleanType TransparentPaintImageChroma(Image *image,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait != BlendPixelTrait)
     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
   /*
     Make image color transparent.
@@ -1047,7 +1053,7 @@ MagickExport MagickBooleanType TransparentPaintImageChroma(Image *image,
   image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
-    dynamic_number_threads(image->columns,image->rows,1)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {