[Image-SIG] Dev notes on PIL core

Noah.org noahspurrier at gmail.com
Tue May 29 18:41:08 CEST 2007


I'm adding a difference_rms(im1, im2) method to ImageChops.
It's fast and works with 1-bit BW, 8-bit gray, and 24-bit color.
I plan to post patches to this group when I'm done testing.
I have gotten only a little bit familiar with the C code. My concern
at this point is the proper way to raise exceptions.
I want to raise an exception if the images are in different modes or
if the sizes do not match (ImagingError_ModeError or ImagingError_Mismatch).
My C function in Chops.c returns a double (the difference RMS value).
Most of the functions in Chops.c return Imaging objects, so
if there is an exception they can easily return an ImagingError.

I want to make my code follow the conventions already being used.
Can anyone suggest the best way to handle raising an exception
from C code that only returns a double?

The heart of the function that I have added to Chops.c looks like this:
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);
}

Yours,
Noah

P.S. I realize RMS comparisons can be done with PIL and Python alone, but
a C implementation is AT LAST 10 times faster than doing something like this
(the fastest way I could find to do it in Python alone):
h1 = Image.open("im1.jpg").histogram()
h2 = Image.open("im2.jpg").histogram()
rms = math.sqrt(reduce(operator.add, map(lambda a,b: (a-b)**2, h1, h2))/len(h1))


More information about the Image-SIG mailing list