GraphicsMagick: ReadXPMImage(): Improve read performance by usin...

GraphicsMagick Commits <[email protected]>
Newsgroups gmane.comp.video.graphicsmagick.cvs
Message-ID <mailman.10892.1667083320.1567.graphicsmagick-commit@lists.sourceforge.net>
changeset c5a31f5a35ec in /hg/GraphicsMagick
details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=c5a31f5a35ec
summary: ReadXPMImage(): Improve read performance by using integer keys.  Trace the colormap.

diffstat:

 ChangeLog                              |    6 +
 VisualMagick/installer/inc/version.isx |    4 +-
 coders/xpm.c                           |  320 ++++++++++++++++++--------------
 magick/version.h                       |    4 +-
 www/Changelog.html                     |   14 +
 5 files changed, 202 insertions(+), 146 deletions(-)

diffs (truncated from 522 to 500 lines):

diff -r ddccc7bf8867 -r c5a31f5a35ec ChangeLog
--- a/ChangeLog	Sat Oct 29 18:37:32 2022 +0200
+++ b/ChangeLog	Sat Oct 29 17:41:33 2022 -0500
@@ -1,4 +1,10 @@
+2022-10-29  Bob Friesenhahn  <[email protected]>
+
+	* coders/xpm.c (ReadXPMImage): Improve read performance by using
+	integer keys.  Trace the colormap.
+
 2022-10-29  Fojtik Jaroslav  <[email protected]>
+
 	* coders/xpm.c (ReadXPMImage): Replace strcmp with faster memcmp.
         It improves 21% performance on my test image.
 
diff -r ddccc7bf8867 -r c5a31f5a35ec VisualMagick/installer/inc/version.isx
--- a/VisualMagick/installer/inc/version.isx	Sat Oct 29 18:37:32 2022 +0200
+++ b/VisualMagick/installer/inc/version.isx	Sat Oct 29 17:41:33 2022 -0500
@@ -10,5 +10,5 @@
 
 #define public MagickPackageName "GraphicsMagick"
 #define public MagickPackageVersion "1.4"
-#define public MagickPackageVersionAddendum ".020221028"
-#define public MagickPackageReleaseDate "snapshot-20221028"
+#define public MagickPackageVersionAddendum ".020221029"
+#define public MagickPackageReleaseDate "snapshot-20221029"
diff -r ddccc7bf8867 -r c5a31f5a35ec coders/xpm.c
--- a/coders/xpm.c	Sat Oct 29 18:37:32 2022 +0200
+++ b/coders/xpm.c	Sat Oct 29 17:41:33 2022 -0500
@@ -56,6 +56,8 @@
 static unsigned int
   WritePICONImage(const ImageInfo *,Image *),
   WriteXPMImage(const ImageInfo *,Image *);
+
+typedef magick_uint32_t xpmkey_t;
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -199,32 +201,29 @@
     i;
 
   for (i=0; i < NumberTargets; i++)
-  {
-    r=data;
-    for (q=targets[i]; *r != '\0'; r++)
     {
-      if (*r != *q)
-        continue;
-      if (!isspace((int) (*(r-1))))
-        continue;
-      p=r;
-      for ( ; ; )
-      {
-        if (*q == '\0')
-          return(r);
-        if (*p++ != *q++)
-          break;
-      }
-      q=targets[i];
+      r=data;
+      for (q=targets[i]; *r != '\0'; r++)
+        {
+          if (*r != *q)
+            continue;
+          if (!isspace((int) (*(r-1))))
+            continue;
+          p=r;
+          for ( ; ; )
+            {
+              if (*q == '\0')
+                return(r);
+              if (*p++ != *q++)
+                break;
+            }
+          q=targets[i];
+        }
     }
-  }
   return((char *) NULL);
 }
 #define ThrowXPMReaderException(code_,reason_,image_) \
 do { \
-  if (keys) \
-    for (i=0; i < (long) image->colors; i++) \
-      MagickFreeResourceLimitedMemory(keys[i]); \
   MagickFreeResourceLimitedMemory(keys); \
   MagickFreeResourceLimitedMemory(textlist); \
   MagickFreeResourceLimitedMemory(xpm_buffer); \
@@ -233,9 +232,10 @@
 
 static Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
+  xpmkey_t
+    *keys = (unsigned int *) NULL;
+
   char
-    key[MaxTextExtent],
-    **keys = (char **) NULL,
     target[MaxTextExtent],
     **textlist = (char **) NULL,
     *xpm_buffer = (char *) NULL;
@@ -243,15 +243,19 @@
   Image
     *image;
 
+  xpmkey_t
+    key;
+
   int
     count;
 
-  unsigned long
+  unsigned int
+    i,
     j,
+    k,
     none;
 
   long
-    k,
     y;
 
   register char
@@ -267,9 +271,6 @@
   register PixelPacket
     *r;
 
-  register long
-    i;
-
   MagickPassFail
     status;
 
@@ -279,7 +280,7 @@
   size_t
     length;
 
-  unsigned long
+  unsigned int
     width; /* characters per pixel */
 
   /*
@@ -329,29 +330,31 @@
     }
   if (xpm_buffer == (char *) NULL)
     ThrowXPMReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+
   /*
     Parse image properties from file header while skipping over comment markers.
   */
   count=0;
   for (p=xpm_buffer; ((p - xpm_buffer) < 512) && (*p != '\0'); p++)
-  {
-    if ((*p != '"') || !isdigit((int) *(p+1)))
-      continue;
-    count=sscanf(p+1,"%lu %lu %u %lu",&image->columns,&image->rows,
-      &image->colors,&width);
-    if (count == 4)
-      {
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "Columns: %lu, Rows: %lu, Colors: %u, Char Per Pixel: %lu",
-                              image->columns, image->rows, image->colors, width);
-        break;
-      }
-  }
-  if ((count != 4) || (width == 0) || (width > 2) ||
+    {
+      if ((*p != '"') || !isdigit((int) *(p+1)))
+        continue;
+      count=sscanf(p+1,"%lu %lu %u %u",&image->columns,&image->rows,
+                   &image->colors,&width);
+      if (count == 4)
+        {
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "Columns: %lu, Rows: %lu, Colors: %u, Char Per Pixel: %u",
+                                image->columns, image->rows, image->colors, width);
+          break;
+        }
+    }
+  if ((count != 4) || (width == 0) || (width > 3) ||
       (image->columns == 0) || (image->rows == 0) ||
       (image->colors == 0) || (image->colors > MaxColormapSize))
     ThrowXPMReaderException(CorruptImageError,ImproperImageHeader,image);
   image->depth=16;
+
   /*
     Remove unquoted characters.
   */
@@ -377,6 +380,7 @@
         ThrowXPMReaderException(CorruptImageError,CorruptImage,image);
       }
   }
+
   /*
     Scan for non-white space binary control codes and reject file if
     they are present.
@@ -387,8 +391,8 @@
   if (*p != '\0')
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "Binary control codes error");
-        ThrowXPMReaderException(CorruptImageError,CorruptImage,image);
+                            "Binary control codes error");
+      ThrowXPMReaderException(CorruptImageError,CorruptImage,image);
     }
   textlist=StringToListMod(xpm_buffer);
   if (textlist == (char **) NULL)
@@ -399,23 +403,23 @@
       for (i=0; textlist[i] != (char *) NULL; i++)
         { };
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "TextList has %lu entries", i);
+                            "TextList has %u entries", i);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "TextList");
       for (i=0; textlist[i] != (char *) NULL; i++)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    %lu: \"%s\"", i, textlist[i]);
+                              "    %u: \"%s\"", i, textlist[i]);
     }
 #endif
 
   /*
     Initialize image structure.
   */
-  keys=MagickAllocateResourceLimitedArray(char **,image->colors,sizeof(char *));
-  if (keys == (char **) NULL)
+  keys=MagickAllocateResourceLimitedArray(xpmkey_t *,image->colors,sizeof(xpmkey_t));
+  if (keys == (xpmkey_t *) NULL)
     ThrowXPMReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-  for (i=0; i < (long) image->colors; i++)
-    keys[i]=(char *) NULL;
+  for (i=0; i < image->colors; i++)
+    keys[i]=0;
   if (!AllocateImageColormap(image,image->colors))
     ThrowXPMReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
@@ -428,123 +432,155 @@
                         "Parsing colormap...");
   colormap_initialized=MagickFalse;
   for (j=0; j < image->colors; j++)
-  {
-    p=textlist[i++];
-    if ((p == (char *) NULL) || (p[0] == '\0'))
-      break;
-    if (image->logging)
-      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    %lu: %s", i-1, textlist[i-1]);
-    if (strlen(p) < width)
-      break;
-    keys[j]=MagickAllocateResourceLimitedMemory(char *,(size_t)width);
-    if (keys[j] == (char *) NULL)
-      ThrowXPMReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    {
+      p=textlist[i++];
+      if ((p == (char *) NULL) || (p[0] == '\0'))
+        break;
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "    %u: %s", i-1, textlist[i-1]);
+      if (strlen(p) < width)
+        break;
+
+      keys[j]=0;
+      for (k=0; k < width; k++)
+        keys[j] |= ((xpmkey_t) p[k]) << (k * 8);
 
-    (void) memcpy(keys[j],p,width);
-    /*
-      Parse color.
-    */
-    (void) strcpy(target,"gray");
-    q=ParseColor(p+width);
-    if (q != (char *) NULL)
-      {
-        while (!isspace((int) (*q)) && (*q != '\0'))
-          q++;
-        (void) strlcpy(target,q,MaxTextExtent);
-        q=ParseColor(target);
-        if (q != (char *) NULL)
-          *q='\0';
-      }
-    (void) MagickStripString(target);
-    if (LocaleCompare(target,"none") == 0)
-      {
-        image->storage_class=DirectClass;
-        image->matte=True;
-        none=j;
-        (void) strcpy(target,"black");
-      }
-    if (!QueryColorDatabase(target,&image->colormap[j],exception))
-      {
-        /* Promote warning to error */
-        exception->severity = CorruptImageError;
-        break;
-      }
-    /* We are going to be done now */
-    if (j+1 == image->colors)
-      colormap_initialized=MagickTrue;
-  }
+      /* printf("Key[%u] =\"%s\" (0x%04X)\n", j, p, (unsigned int) keys[j]); */
+      /*
+        Parse color.
+      */
+      (void) strcpy(target,"gray");
+      q=ParseColor(p+width);
+      if (q != (char *) NULL)
+        {
+          while (!isspace((int) (*q)) && (*q != '\0'))
+            q++;
+          (void) strlcpy(target,q,MaxTextExtent);
+          q=ParseColor(target);
+          if (q != (char *) NULL)
+            *q='\0';
+        }
+      (void) MagickStripString(target);
+      if (LocaleCompare(target,"none") == 0)
+        {
+          image->storage_class=DirectClass;
+          image->matte=True;
+          none=j;
+          (void) strcpy(target,"black");
+        }
+      if (!QueryColorDatabase(target,&image->colormap[j],exception))
+        {
+          /* Promote warning to error */
+          exception->severity = CorruptImageError;
+          break;
+        }
+      /* We are going to be done now */
+      if (j+1 == image->colors)
+        colormap_initialized=MagickTrue;
+    }
   if (!colormap_initialized)
     ThrowXPMReaderException(CorruptImageError,CorruptImage,image);
+
+  /*
+    Log the XPM Colormap if logging is enabled.
+  */
+  if (image->logging)
+    {
+      char
+        name[MaxTextExtent];
+
+      unsigned int
+        ii;
+
+      register PixelPacket
+        *p;
+
+      /*
+        Display image colormap.
+      */
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "XPM Colormap (Depth %u):", image->depth);
+      p=image->colormap;
+      for (ii=0; ii < image->colors; ii++)
+        {
+          char
+            tuple[MaxTextExtent];
+
+          GetColorTuple(p,image->depth,image->matte,False,tuple);
+          (void) QueryColorname(image,p,X11Compliance,name,&image->exception);
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "    %" MAGICK_SIZE_T_F "u: %.1024s\t  %.1024s",
+                                (MAGICK_SIZE_T) ii,tuple,name);
+          p++;
+        }
+    }
+
   image->depth=GetImageDepth(image,&image->exception);
   image->depth=NormalizeDepthToOctet(image->depth);
+
   j=0;
-  key[width]='\0';
+  key=0;
   if (!image_info->ping)
     {
       /*
         Read image pixels.
       */
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                        "Parsing pixels...");
+                            "Parsing pixels...");
       for (y=0; y < (long) image->rows; y++)
-      {
-        p=textlist[i++];
-        if ((p == (char *) NULL) || (p[0] == '\0'))
-          break;
-        if (image->logging)
-          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    %lu: %s", i-1, textlist[i-1]);
-        r=SetImagePixelsEx(image,0,y,image->columns,1,exception);
-        if (r == (PixelPacket *) NULL)
-          break;
-        indexes=AccessMutableIndexes(image);
-        for (x=0; x < (long) image->columns; x++)
         {
-          /* (void) strncpy(key,p,width); */
-          for(k=0; k < (long) width; k++)
+          p=textlist[i++];
+          if ((p == (char *) NULL) || (p[0] == '\0'))
+            break;
+          if (image->logging)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "    %u: %s", i-1, textlist[i-1]);
+          r=SetImagePixelsEx(image,0,y,image->columns,1,exception);
+          if (r == (PixelPacket *) NULL)
+            break;
+          indexes=AccessMutableIndexes(image);
+          for (x=0; x < (long) image->columns; x++)
             {
-              key[k]=p[k];
-              if (p[k] == '\0')
+              key=0;
+              for (k=0; k < width; k++)
                 {
-                  status=MagickFail;
-                  break;
+                  if (p[k] == '\0')
+                    {
+                      status=MagickFail;
+                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                            "Unexpected end of row %ld! (k=%u)", y, k);
+                      break;
+                    }
+                  key |= ((unsigned int) p[k]) << (k * 8);
                 }
+              if (MagickFail == status)
+                break;
+              /* printf("Key[%ld,%ld] = 0x%04X\n", x, y, (unsigned int) key); */
+              if (key != keys[j])
+                for (j=0; j < Max(image->colors-1,1); j++)
+                  if (key == keys[j])
+                    break;
+              VerifyColormapIndex(image,j);
+              if (image->storage_class == PseudoClass)
+                indexes[x]=(IndexPacket) j;
+              *r=image->colormap[j];
+              r->opacity=(Quantum)
+                (j == none ? TransparentOpacity : OpaqueOpacity);
+              r++;
+              p+=width;
             }
-          if(MagickFail == status)
-              break;
-          if(memcmp(key,keys[j],width) != 0)
-          {
-            j = Max(image->colors,1);
-            while(j-- > 0)	/* When j underflows, the VerifyColormapIndex stops reading. */
-            {
-              if(memcmp(key,keys[j],width) == 0)
-                break;
-            }
-          }
-
-          VerifyColormapIndex(image,j);
-          if (image->storage_class == PseudoClass)
-            indexes[x]=(IndexPacket) j;
-          *r=image->colormap[j];
-          r->opacity=(Quantum)
-            (j == none ? TransparentOpacity : OpaqueOpacity);
-          r++;
-          p+=width;
+          if (MagickFail == status)
+            break;
+          if (!SyncImagePixelsEx(image,exception))
+            break;
         }
-        if (MagickFail == status)
-          break;
-        if (!SyncImagePixelsEx(image,exception))
-          break;
-      }
       if (y < (long) image->rows)
         ThrowXPMReaderException(CorruptImageError,InsufficientImageDataInFile,image);
     }
   /*
     Free resources.
   */
-  for (i=0; i < (long) image->colors; i++)
-    MagickFreeResourceLimitedMemory(keys[i]);
   MagickFreeResourceLimitedMemory(keys);
   MagickFreeResourceLimitedMemory(textlist);
   MagickFreeResourceLimitedMemory(xpm_buffer);
diff -r ddccc7bf8867 -r c5a31f5a35ec magick/version.h
--- a/magick/version.h	Sat Oct 29 18:37:32 2022 +0200
+++ b/magick/version.h	Sat Oct 29 17:41:33 2022 -0500
@@ -38,8 +38,8 @@
 #define MagickLibVersion  0x272400
 #define MagickLibVersionText  "1.4"
 #define MagickLibVersionNumber 27,24,0
-#define MagickChangeDate   "20221028"
-#define MagickReleaseDate  "snapshot-20221028"
+#define MagickChangeDate   "20221029"
+#define MagickReleaseDate  "snapshot-20221029"
 
 /*
   The MagickLibInterfaceNewest and MagickLibInterfaceOldest defines
diff -r ddccc7bf8867 -r c5a31f5a35ec www/Changelog.html
--- a/www/Changelog.html	Sat Oct 29 18:37:32 2022 +0200
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.