]> granicus.if.org Git - imagemagick/commitdiff
Return connected components object for post analysis
authorCristy <urban-warrior@imagemagick.org>
Tue, 29 Dec 2015 22:28:37 +0000 (17:28 -0500)
committerCristy <urban-warrior@imagemagick.org>
Tue, 29 Dec 2015 22:28:37 +0000 (17:28 -0500)
MagickCore/vision.c
MagickCore/vision.h
MagickWand/mogrify.c
MagickWand/operation.c
PerlMagick/Magick.xs
PerlMagick/quantum/quantum.xs.in

index af80c583492583a2e5bbbbc389d53755873406ea..7b3dced890b846e78d2a2f2c9ab597aaec1f18dc 100644 (file)
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  ConnectedComponentsImage() returns the connected-components of the image
-%  uniquely labeled.  Choose from 4 or 8-way connectivity.
+%  uniquely labeled.  The returned connected components image colors member
+%  defines the number of unique objects.  Choose from 4 or 8-way connectivity.
+%
+%  You are responsible for freeing the connected components objects resources
+%  with this statement;
+%
+%    objects = (CCObjectInfo *) RelinquishMagickMemory(objects);
 %
 %  The format of the ConnectedComponentsImage method is:
 %
 %      Image *ConnectedComponentsImage(const Image *image,FILE *file,
 %        const size_t connectivity,const MagickBooleanType verbose,
-%        ExceptionInfo *exception)
+%        CCObjectInfo **objects,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o verbose: A value other than zero prints more detailed information
 %      about the image.
 %
+%    o objects: return the attributes of each unique object.
+%
 %    o exception: return any errors or warnings in this structure.
 %
 */
 
-typedef struct _CCObject
+static int CCObjectInfoCompare(const void *x,const void *y)
 {
-  ssize_t
-    id;
-
-  RectangleInfo
-    bounding_box;
-
-  PixelInfo
-    color;
-
-  PointInfo
-    centroid;
-
-  double
-    area,
-    census;
-} CCObject;
-
-static int CCObjectCompare(const void *x,const void *y)
-{
-  CCObject
+  CCObjectInfo
     *p,
     *q;
 
-  p=(CCObject *) x;
-  q=(CCObject *) y;
+  p=(CCObjectInfo *) x;
+  q=(CCObjectInfo *) y;
   return((int) (q->area-(ssize_t) p->area));
 }
 
 MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
   const size_t connectivity,const MagickBooleanType verbose,
-  ExceptionInfo *exception)
+  CCObjectInfo **objects,ExceptionInfo *exception)
 {
 #define ConnectedComponentsImageTag  "ConnectedComponents/Image"
 
@@ -154,12 +143,12 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
     *image_view,
     *component_view;
 
+  CCObjectInfo
+    *object;
+
   char
     *p;
 
-  CCObject
-    *object;
-
   const char
     *artifact;
 
@@ -200,6 +189,8 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickCoreSignature);
+  if (objects != (CCObjectInfo **) NULL)
+    *objects=(CCObjectInfo *) NULL;
   component_image=CloneImage(image,image->columns,image->rows,MagickTrue,
     exception);
   if (component_image == (Image *) NULL)
@@ -227,8 +218,8 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
     }
   for (n=0; n < (ssize_t) (image->columns*image->rows); n++)
     (void) SetMatrixElement(equivalences,n,0,&n);
-  object=(CCObject *) AcquireQuantumMemory(MaxColormapSize,sizeof(*object));
-  if (object == (CCObject *) NULL)
+  object=(CCObjectInfo *) AcquireQuantumMemory(MaxColormapSize,sizeof(*object));
+  if (object == (CCObjectInfo *) NULL)
     {
       equivalences=DestroyMatrixInfo(equivalences);
       component_image=DestroyImage(component_image);
@@ -440,7 +431,7 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
   equivalences=DestroyMatrixInfo(equivalences);
   if (n > (ssize_t) MaxColormapSize)
     {
-      object=(CCObject *) RelinquishMagickMemory(object);
+      object=(CCObjectInfo *) RelinquishMagickMemory(object);
       component_image=DestroyImage(component_image);
       ThrowImageException(ResourceLimitError,"TooManyObjects");
     }
@@ -464,7 +455,7 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
   if (area_threshold > 0.0)
     {
       /*
-        Merge objects below area threshold.
+        Merge object below area threshold.
       */
       component_view=AcquireAuthenticCacheView(component_image,exception);
       for (i=0; i < (ssize_t) component_image->colors; i++)
@@ -557,18 +548,13 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
         Replace object with mean color.
       */
       for (i=0; i < (ssize_t) component_image->colors; i++)
-      {
-        component_image->colormap[i].red=object[i].color.red;
-        component_image->colormap[i].green=object[i].color.green;
-        component_image->colormap[i].blue=object[i].color.blue;
-        component_image->colormap[i].alpha=object[i].color.alpha;
-      }
+        component_image->colormap[i]=object[i].color;
     }
   artifact=GetImageArtifact(image,"connected-components:keep");
   if (artifact != (const char *) NULL)
     {
       /*
-        Keep these objects (make others transparent).
+        Keep these object (make others transparent).
       */
       for (i=0; i < (ssize_t) component_image->colors; i++)
         object[i].census=0;
@@ -603,7 +589,7 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
   if (artifact != (const char *) NULL)
     {
       /*
-        Remove these objects (make them transparent).
+        Remove these object (make them transparent).
       */
       for (p=(char *) artifact; *p != '\0';)
       {
@@ -632,7 +618,7 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
   if (verbose != MagickFalse)
     {
       /*
-        Report statistics on unique objects.
+        Report statistics on unique object.
       */
       for (i=0; i < (ssize_t) component_image->colors; i++)
       {
@@ -691,7 +677,7 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
       }
       component_view=DestroyCacheView(component_view);
       qsort((void *) object,component_image->colors,sizeof(*object),
-        CCObjectCompare);
+        CCObjectInfoCompare);
       (void) fprintf(file,
         "Objects (id: bounding-box centroid area mean-color):\n");
       for (i=0; i < (ssize_t) component_image->colors; i++)
@@ -712,6 +698,9 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,FILE *file,
           object[i].centroid.y,(double) object[i].area,mean_color);
       }
     }
-  object=(CCObject *) RelinquishMagickMemory(object);
+  if (objects == (CCObjectInfo **) NULL)
+    object=(CCObjectInfo *) RelinquishMagickMemory(object);
+  else
+    *objects=object;
   return(component_image);
 }
index dc22a3f10d91af77de08c1e0f9cbf85798905fdd..3556f30f5bcedff3dee10b73bdc6eb73d0fb5d81 100644 (file)
 extern "C" {
 #endif
 
+typedef struct _CCObjectInfo
+{
+  ssize_t
+    id;
+
+  RectangleInfo
+    bounding_box;
+
+  PixelInfo
+    color;
+
+  PointInfo
+    centroid;
+
+  double
+    area,
+    census;
+} CCObjectInfo;
+
 extern MagickExport Image
   *ConnectedComponentsImage(const Image *,FILE *,const size_t,
-    const MagickBooleanType,ExceptionInfo *);
+    const MagickBooleanType,CCObjectInfo **,ExceptionInfo *);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }
index 407879f84311b06f815ce08d043b8055d4f12eca..5c19922f43b5849ce93b3344160206fcdee9cda5 100644 (file)
@@ -1196,7 +1196,7 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
             (void) SyncImageSettings(mogrify_info,*image,exception);
             mogrify_image=ConnectedComponentsImage(*image,stdout,
               (size_t) StringToInteger(argv[i+1]),mogrify_info->verbose,
-              exception);
+              (CCObjectInfo **) NULL,exception);
             break;
           }
         if (LocaleCompare("contrast",option+1) == 0)
index e877c5fa23473e7e48f7440d439da6e306c9b354..486a50bbbb5e66f0033a49040728034e999cfe15 100644 (file)
@@ -2103,7 +2103,8 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           new_image=ConnectedComponentsImage(_image,stdout,(size_t)
-            StringToInteger(arg1),_image_info->verbose,_exception);
+            StringToInteger(arg1),_image_info->verbose,(CCObjectInfo **) NULL,
+            _exception);
           break;
         }
       if (LocaleCompare("contrast",option+1) == 0)
index 787ddd7ab9a8389b1bcda057dfee12464ef7327f..556203f0d8b1b5e4205d7525a6573d237acc765a 100644 (file)
@@ -11271,7 +11271,7 @@ Mogrify(ref,...)
             verbose=argument_list[1].integer_reference != 0 ?
               MagickTrue : MagickFalse;
           image=ConnectedComponentsImage(image,stdout,connectivity,verbose,
-            exception);
+            (CCObjectInfo **) NULLexception);
           break;
         }
         case 143:  /* Copy */
index b621fab077fb03579966f80578bea4b296dcc48e..0c458fdb858c666248cee8ebe1e9418f6704b42f 100644 (file)
@@ -11269,7 +11269,7 @@ Mogrify(ref,...)
             verbose=argument_list[1].integer_reference != 0 ?
               MagickTrue : MagickFalse;
           image=ConnectedComponentsImage(image,stdout,connectivity,verbose,
-            exception);
+            (CCObjectInfo **) NULL,exception);
           break;
         }
         case 143:  /* Copy */