Source

pinyomi / pixel / comparePng.pyx

Full commit
# -*- coding: utf-8 -*-
#----------------------------------------------------------------------------#
# comparePng.pyx
# Lars Yencken <lljy@csse.unimelb.edu.au>
# vim: ts=4 sw=4 sts=4 et tw=78:
# Tue May 13 17:03:21 2008
#
#----------------------------------------------------------------------------#

import os

#----------------------------------------------------------------------------# 

cdef extern from "math.h":
    double fabs(double x)
    double pow(double x, double exp)

#----------------------------------------------------------------------------#

cdef extern from "stdio.h":
    ctypedef struct FILE:
        pass

    FILE* fopen(char* filename, char* mode)
    void fclose(FILE*)

#----------------------------------------------------------------------------# 

cdef extern from "gd.h":
    ctypedef struct gdImage:
        pass

    gdImage* gdImageCreateFromPng(FILE* fd)
    void gdImageDestroy(gdImage* image)
    int gdImageSX(gdImage* image)
    int gdImageSY(gdImage* image)
    int gdImageGetPixel(gdImage* image, int x, int y)
    int gdImageRed(gdImage* image, int pixel)
    int gdImageGreen(gdImage* image, int pixel)
    int gdImageBlue(gdImage* image, int pixel)

#----------------------------------------------------------------------------# 

class ImageSizeMismatch(Exception): pass

cdef class PngImage:
    cdef gdImage* _image
    cdef int _width
    cdef int _height

    def __cinit__(self, filename):
        cdef FILE* f
        if not os.path.exists(filename):
            raise IOError, 'file does not exist: %s' % filename

        f = fopen(filename, "rb")
        if f == NULL:
            raise IOError, 'error opening file: %s' % filename 
        self._image = gdImageCreateFromPng(f)
        fclose(f)

        self._width = gdImageSX(self._image)
        self._height = gdImageSY(self._image)

    cdef double getLuminancePixel(self, int x, int y):
        "Fetch the luminance of the pixel at (x, y)."
        cdef int red, green, blue, pixel
        pixel = gdImageGetPixel(self._image, x, y)
        red = gdImageRed(self._image, pixel)
        green = gdImageGreen(self._image, pixel)
        blue = gdImageBlue(self._image, pixel)
        return (0.2126*red + 0.7152*green + 0.0722*blue)/255.0;

    def norm(self, PngImage rhs not None, double n):
        cdef int i, j
        cdef double sum, diff

        if self._width != rhs._width or self._height != rhs._height:
            raise ImageSizeMismatch

        if n < 1:
            raise ValueError, "n must be >= 1: %d" % n

        sum = 0.0
        for y from  0 <= y < self._height:
            for x from 0 <= x < self._width:
                sum = sum + pow(fabs(self.getLuminancePixel(x, y) - \
                        rhs.getLuminancePixel(x, y)), n)

        return pow(sum, 1.0/n) / (self._width * self._height)

    def __dealloc__(self):
        if self._image != NULL:
            gdImageDestroy(self._image)

#----------------------------------------------------------------------------#