PIL patches

From Noah.org
Revision as of 13:22, 29 May 2007 by Root (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

This is a patch against the Python Imaging Library Imaging-1.1.6. This add the method ImageChops.difference_rms(im1, im2) which returns a float giving the RMS difference between the two given images. This is about 10 times faster than doing it in Python. This can be used to detect changes in images (motion) or to compare the effect of different image operations. If the two images are exactly equal then differnce_rms() will return 0.0. As the images diverge the value returned will increase. It will always be a positive number. In general, the greater the difference between the two images then the greater the RMS difference will be.

diff -r -C 6 -x.svn -x'*.jpg' -x'*.png' -x'*.gif' -x'*.swp' -x'*.a' -x'*.so' -x'*.o' -x'*.pyc' -x'*.exe' -x'*.class' -xCVS -xcore -xa.out /home/noah/Imaging-1.1.6/_imaging.c ./_imaging.c
*** /home/noah/Imaging-1.1.6/_imaging.c 2006-12-03 04:20:39.000000000 -0800
--- ./_imaging.c        2007-05-29 10:21:15.000000000 -0700
***************
*** 1848,1859 ****
--- 1848,1879 ----
      if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
        return NULL;
  
      return PyImagingNew(ImagingChopDifference(self->image, imagep->image));
  }
  
+ static PyObject*
+ _chop_difference_rms(ImagingObject* self, PyObject* args)
+ {
+     double rms;
+     ImagingObject* imagep;
+ 
+     if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+         return Py_BuildValue("d", (double)0.0);
+ 
+     rms = ImagingChopDifferenceRMS(self->image, imagep->image);
+     if (rms == -1.0) {
+         return ImagingError_ModeError();
+     }
+     if (rms == -2.0) {
+         return ImagingError_Mismatch();
+     }
+ 
+     return Py_BuildValue("d", rms);
+ }
+ 
  static PyObject* 
  _chop_multiply(ImagingObject* self, PyObject* args)
  {
      ImagingObject* imagep;
  
      if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
***************
*** 2821,2832 ****
--- 2841,2853 ----
  #ifdef WITH_IMAGECHOPS
      /* Channel operations (ImageChops) */
      {"chop_invert", (PyCFunction)_chop_invert, 1},
      {"chop_lighter", (PyCFunction)_chop_lighter, 1},
      {"chop_darker", (PyCFunction)_chop_darker, 1},
      {"chop_difference", (PyCFunction)_chop_difference, 1},
+     {"chop_difference_rms", (PyCFunction)_chop_difference_rms, 1},
      {"chop_multiply", (PyCFunction)_chop_multiply, 1},
      {"chop_screen", (PyCFunction)_chop_screen, 1},
      {"chop_add", (PyCFunction)_chop_add, 1},
      {"chop_subtract", (PyCFunction)_chop_subtract, 1},
      {"chop_add_modulo", (PyCFunction)_chop_add_modulo, 1},
      {"chop_subtract_modulo", (PyCFunction)_chop_subtract_modulo, 1},
diff -r -C 6 -x.svn -x'*.jpg' -x'*.png' -x'*.gif' -x'*.swp' -x'*.a' -x'*.so' -x'*.o' -x'*.pyc' -x'*.exe' -x'*.class' -xCVS -xcore -xa.out /home/noah/Imaging-1.1.6/libImaging/Chops.c ./libImaging/Chops.c
*** /home/noah/Imaging-1.1.6/libImaging/Chops.c 2006-12-03 03:37:25.000000000 -0800
--- ./libImaging/Chops.c        2007-05-29 10:29:04.000000000 -0700
***************
*** 90,101 ****
--- 90,132 ----
  Imaging
  ImagingChopDifference(Imaging imIn1, Imaging imIn2)
  {
      CHOP(abs((int) in1[x] - (int) in2[x]), NULL);
  }
  
+ double ImagingChopDifferenceRMS(Imaging imIn1, Imaging imIn2)
+ {
+     int x, y;
+     long count, n, ns;
+ 
+     if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 ||
+         (strcmp(imIn1->mode, imIn2->mode) != 0))
+         return -1.0; //(Imaging) ImagingError_ModeError();
+ 
+     if (imIn1->type  != imIn2->type  ||
+         imIn1->bands != imIn2->bands ||
+         imIn1->ysize != imIn2->ysize ||
+         imIn1->xsize != imIn2->xsize)
+         return -2.0; //(Imaging) ImagingError_Mismatch();
+ 
+     ns = 0;
+     count = 0;
+     for (y = 0; y < imIn1->ysize; ++y)
+     {
+         UINT8* in1 = (UINT8*) imIn1->image[y];
+         UINT8* in2 = (UINT8*) imIn2->image[y];
+         for (x = 0; x < imIn1->linesize; ++x)
+         {
+             ++ count;
+             n = (long) in1[x] - (long) in2[x];
+             ns += n*n;
+         }
+     }
+     return sqrt((double)ns / (double)count);
+ }
+ 
  Imaging
  ImagingChopMultiply(Imaging imIn1, Imaging imIn2)
  {
      CHOP((int) in1[x] * (int) in2[x] / 255, NULL);
  }
  
diff -r -C 6 -x.svn -x'*.jpg' -x'*.png' -x'*.gif' -x'*.swp' -x'*.a' -x'*.so' -x'*.o' -x'*.pyc' -x'*.exe' -x'*.class' -xCVS -xcore -xa.out /home/noah/Imaging-1.1.6/libImaging/Imaging.h ./libImaging/Imaging.h
*** /home/noah/Imaging-1.1.6/libImaging/Imaging.h       2006-12-03 03:37:25.000000000 -0800
--- ./libImaging/Imaging.h      2007-05-27 19:48:14.000000000 -0700
***************
*** 307,318 ****
--- 307,319 ----
  
  /* Channel operations */
  /* any mode, except "F" */
  extern Imaging ImagingChopLighter(Imaging imIn1, Imaging imIn2);
  extern Imaging ImagingChopDarker(Imaging imIn1, Imaging imIn2);
  extern Imaging ImagingChopDifference(Imaging imIn1, Imaging imIn2);
+ extern double  ImagingChopDifferenceRMS(Imaging imIn1, Imaging imIn2);
  extern Imaging ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
  extern Imaging ImagingChopScreen(Imaging imIn1, Imaging imIn2);
  extern Imaging ImagingChopAdd(
      Imaging imIn1, Imaging imIn2, float scale, int offset);
  extern Imaging ImagingChopSubtract(
      Imaging imIn1, Imaging imIn2, float scale, int offset);
diff -r -C 6 -x.svn -x'*.jpg' -x'*.png' -x'*.gif' -x'*.swp' -x'*.a' -x'*.so' -x'*.o' -x'*.pyc' -x'*.exe' -x'*.class' -xCVS -xcore -xa.out /home/noah/Imaging-1.1.6/PIL/ImageChops.py ./PIL/ImageChops.py
*** /home/noah/Imaging-1.1.6/PIL/ImageChops.py  2006-12-03 03:37:15.000000000 -0800
--- ./PIL/ImageChops.py 2007-05-27 20:07:09.000000000 -0700
***************
*** 120,131 ****
--- 120,149 ----
  
      image1.load()
      image2.load()
      return image1._new(image1.im.chop_difference(image2.im))
  
  ##
+ # Calculate RMS difference
+ # <p>
+ # Returns the RMS of the difference between the two images.
+ #
+ # @param image1 First image.
+ # @param image1 Second image.
+ # @return float.
+ 
+ def difference_rms(image1, image2):
+     """This returns the RMS difference of two images.
+     This returns a double float
+     """
+ 
+     image1.load()
+     image2.load()
+     return image1.im.chop_difference_rms(image2.im)
+ 
+ ##
  # Superimpose positive images
  # (image1 * image2 / MAX).
  # <p>
  # Superimposes two images on top of each other. If you multiply an
  # image with a solid black image, the result is black. If you multiply
  # with a solid white image, the image is unaffected.
diff -r -C 6 -x.svn -x'*.jpg' -x'*.png' -x'*.gif' -x'*.swp' -x'*.a' -x'*.so' -x'*.o' -x'*.pyc' -x'*.exe' -x'*.class' -xCVS -xcore -xa.out /home/noah/Imaging-1.1.6/setup.py ./setup.py
*** /home/noah/Imaging-1.1.6/setup.py   2006-12-03 03:37:29.000000000 -0800
--- ./setup.py  2007-03-14 11:27:25.000000000 -0700
***************
*** 137,148 ****
--- 137,150 ----
              add_directory(library_dirs, "/sw/lib")
              add_directory(include_dirs, "/sw/include")
              # darwin ports installation directories
              add_directory(library_dirs, "/opt/local/lib")
              add_directory(include_dirs, "/opt/local/include")
  
+         #add_directory(library_dirs, "")
+         add_directory(include_dirs, "/usr/include/tcl8.4")
          add_directory(library_dirs, "/usr/local/lib")
          # FIXME: check /opt/stuff directories here?
  
          prefix = sysconfig.get_config_var("prefix")
          if prefix:
              add_directory(library_dirs, os.path.join(prefix, "lib"))
***************
*** 192,203 ****
--- 194,206 ----
  
          #
          # add standard directories
  
          add_directory(library_dirs, "/usr/local/lib")
          add_directory(include_dirs, "/usr/local/include")
+         add_directory(include_dirs, "/usr/include/tcl8.4")
  
          add_directory(library_dirs, "/usr/lib")
          add_directory(include_dirs, "/usr/include")
  
          #
          # insert new dirs *before* default libs, to avoid conflicts
***************
*** 244,255 ****
--- 247,259 ----
              if freetype_version:
                  feature.freetype = "freetype"
                  feature.freetype_version = freetype_version
                  if dir:
                      add_directory(self.compiler.include_dirs, dir, 0)
  
+         add_directory(include_dirs, "/usr/include/tcl8.4")
          if _tkinter:
              # the library names may vary somewhat (e.g. tcl84 or tcl8.4)
              version = TCL_VERSION[0] + TCL_VERSION[2]
              if find_library_file(self, "tcl" + version):
                  feature.tcl = "tcl" + version
              elif find_library_file(self, "tcl" + TCL_VERSION):