Add image comparison API to imagemagick bindings

This commit is contained in:
Kovid Goyal 2013-02-13 17:31:36 +05:30
parent f897286e3c
commit 85b5fab4ab
4 changed files with 77 additions and 25 deletions

View File

@ -200,6 +200,9 @@ class Image(_magick.Image): # {{{
raise ValueError('left and/or top out of bounds')
_magick.Image.compose(self, img, int(left), int(top), op)
def compare(self, img, metric='RootMeanSquaredErrorMetric'):
return _magick.Image.compare(self, img, getattr(_magick, metric))
def font_metrics(self, drawing_wand, text):
if isinstance(text, unicode):
text = text.encode('UTF-8')

View File

@ -50,7 +50,7 @@ def get_value(const):
def main():
constants = []
for x in ('resample', 'image', 'draw', 'distort', 'composite', 'geometry',
'colorspace'):
'colorspace', 'compare'):
constants += list(parse_enums('magick/%s.h'%x))
base = os.path.dirname(__file__)
constants = [

View File

@ -494,6 +494,7 @@ typedef struct {
// Method declarations {{{
static PyObject* magick_Image_compose(magick_Image *self, PyObject *args);
static PyObject* magick_Image_compare(magick_Image *self, PyObject *args);
static PyObject* magick_Image_copy(magick_Image *self, PyObject *args);
static PyObject* magick_Image_texture(magick_Image *self, PyObject *args);
// }}}
@ -1196,6 +1197,10 @@ static PyMethodDef magick_Image_methods[] = {
"compose(img, left, top, op) \n\n Compose img using operation op at (left, top)"
},
{"compare", (PyCFunction)magick_Image_compare, METH_VARARGS,
"compose(img, metric) \n\n Compare images using the specified metric. (One of AbsoluteErrorMetric, MeanAbsoluteErrorMetric, MeanErrorPerPixelMetric, MeanSquaredErrorMetric, PeakAbsoluteErrorMetric, PeakSignalToNoiseRatioMetric, RootMeanSquaredErrorMetric, NormalizedCrossCorrelationErrorMetric, FuzzErrorMetric)"
},
{"texture", (PyCFunction)magick_Image_texture, METH_VARARGS,
"texture(img)) \n\n Repeatedly tile img across and down the canvas."
},
@ -1380,6 +1385,26 @@ magick_Image_compose(magick_Image *self, PyObject *args)
}
// }}}
// Image.compose {{{
static PyObject *
magick_Image_compare(magick_Image *self, PyObject *args)
{
PyObject *img;
MetricType metric;
magick_Image *src;
double distortion = 0;
NULL_CHECK(NULL)
if (!PyArg_ParseTuple(args, "O!i", &magick_ImageType, &img, &metric)) return NULL;
src = (magick_Image*)img;
if (!IsMagickWand(src->wand)) {PyErr_SetString(PyExc_TypeError, "Not a valid ImageMagick wand"); return NULL;}
MagickCompareImages(self->wand, src->wand, metric, &distortion);
return Py_BuildValue("d", distortion);
}
// }}}
// Image.clone {{{
static PyObject *
magick_Image_copy(magick_Image *self, PyObject *args)

View File

@ -14,25 +14,24 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "CubicFilter", 10);
PyModule_AddIntConstant(m, "CatromFilter", 11);
PyModule_AddIntConstant(m, "MitchellFilter", 12);
PyModule_AddIntConstant(m, "LanczosFilter", 13);
PyModule_AddIntConstant(m, "BesselFilter", 14);
PyModule_AddIntConstant(m, "SincFilter", 15);
PyModule_AddIntConstant(m, "JincFilter", 13);
PyModule_AddIntConstant(m, "SincFilter", 14);
PyModule_AddIntConstant(m, "SincFastFilter", 15);
PyModule_AddIntConstant(m, "KaiserFilter", 16);
PyModule_AddIntConstant(m, "WelshFilter", 17);
PyModule_AddIntConstant(m, "ParzenFilter", 18);
PyModule_AddIntConstant(m, "LagrangeFilter", 19);
PyModule_AddIntConstant(m, "BohmanFilter", 20);
PyModule_AddIntConstant(m, "BartlettFilter", 21);
PyModule_AddIntConstant(m, "SentinelFilter", 22);
PyModule_AddIntConstant(m, "UndefinedInterpolatePixel", 0);
PyModule_AddIntConstant(m, "AverageInterpolatePixel", 1);
PyModule_AddIntConstant(m, "BicubicInterpolatePixel", 2);
PyModule_AddIntConstant(m, "BilinearInterpolatePixel", 3);
PyModule_AddIntConstant(m, "FilterInterpolatePixel", 4);
PyModule_AddIntConstant(m, "IntegerInterpolatePixel", 5);
PyModule_AddIntConstant(m, "MeshInterpolatePixel", 6);
PyModule_AddIntConstant(m, "NearestNeighborInterpolatePixel", 7);
PyModule_AddIntConstant(m, "SplineInterpolatePixel", 8);
PyModule_AddIntConstant(m, "BohmanFilter", 19);
PyModule_AddIntConstant(m, "BartlettFilter", 20);
PyModule_AddIntConstant(m, "LagrangeFilter", 21);
PyModule_AddIntConstant(m, "LanczosFilter", 22);
PyModule_AddIntConstant(m, "LanczosSharpFilter", 23);
PyModule_AddIntConstant(m, "Lanczos2Filter", 24);
PyModule_AddIntConstant(m, "Lanczos2SharpFilter", 25);
PyModule_AddIntConstant(m, "RobidouxFilter", 26);
PyModule_AddIntConstant(m, "RobidouxSharpFilter", 27);
PyModule_AddIntConstant(m, "CosineFilter", 28);
PyModule_AddIntConstant(m, "SplineFilter", 29);
PyModule_AddIntConstant(m, "SentinelFilter", 30);
PyModule_AddIntConstant(m, "UndefinedAlphaChannel", 0);
PyModule_AddIntConstant(m, "ActivateAlphaChannel", 1);
PyModule_AddIntConstant(m, "BackgroundAlphaChannel", 2);
@ -44,6 +43,8 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "SetAlphaChannel", 8);
PyModule_AddIntConstant(m, "ShapeAlphaChannel", 9);
PyModule_AddIntConstant(m, "TransparentAlphaChannel", 10);
PyModule_AddIntConstant(m, "FlattenAlphaChannel", 11);
PyModule_AddIntConstant(m, "RemoveAlphaChannel", 12);
PyModule_AddIntConstant(m, "UndefinedType", 0);
PyModule_AddIntConstant(m, "BilevelType", 1);
PyModule_AddIntConstant(m, "GrayscaleType", 2);
@ -152,16 +153,20 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "ArcDistortion", 9);
PyModule_AddIntConstant(m, "PolarDistortion", 10);
PyModule_AddIntConstant(m, "DePolarDistortion", 11);
PyModule_AddIntConstant(m, "BarrelDistortion", 12);
PyModule_AddIntConstant(m, "BarrelInverseDistortion", 13);
PyModule_AddIntConstant(m, "ShepardsDistortion", 14);
PyModule_AddIntConstant(m, "SentinelDistortion", 15);
PyModule_AddIntConstant(m, "Cylinder2PlaneDistortion", 12);
PyModule_AddIntConstant(m, "Plane2CylinderDistortion", 13);
PyModule_AddIntConstant(m, "BarrelDistortion", 14);
PyModule_AddIntConstant(m, "BarrelInverseDistortion", 15);
PyModule_AddIntConstant(m, "ShepardsDistortion", 16);
PyModule_AddIntConstant(m, "ResizeDistortion", 17);
PyModule_AddIntConstant(m, "SentinelDistortion", 18);
PyModule_AddIntConstant(m, "UndefinedColorInterpolate", 0);
PyModule_AddIntConstant(m, "BarycentricColorInterpolate", 1);
PyModule_AddIntConstant(m, "BilinearColorInterpolate", 7);
PyModule_AddIntConstant(m, "PolynomialColorInterpolate", 8);
PyModule_AddIntConstant(m, "ShepardsColorInterpolate", 14);
PyModule_AddIntConstant(m, "VoronoiColorInterpolate", 15);
PyModule_AddIntConstant(m, "ShepardsColorInterpolate", 16);
PyModule_AddIntConstant(m, "VoronoiColorInterpolate", 18);
PyModule_AddIntConstant(m, "InverseColorInterpolate", 19);
PyModule_AddIntConstant(m, "UndefinedCompositeOp", 0);
PyModule_AddIntConstant(m, "NoCompositeOp", 1);
PyModule_AddIntConstant(m, "ModulusAddCompositeOp", 2);
@ -198,7 +203,7 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "LightenCompositeOp", 33);
PyModule_AddIntConstant(m, "LinearLightCompositeOp", 34);
PyModule_AddIntConstant(m, "LuminizeCompositeOp", 35);
PyModule_AddIntConstant(m, "MinusCompositeOp", 36);
PyModule_AddIntConstant(m, "MinusDstCompositeOp", 36);
PyModule_AddIntConstant(m, "ModulateCompositeOp", 37);
PyModule_AddIntConstant(m, "MultiplyCompositeOp", 38);
PyModule_AddIntConstant(m, "OutCompositeOp", 39);
@ -217,7 +222,7 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "ModulusSubtractCompositeOp", 52);
PyModule_AddIntConstant(m, "ThresholdCompositeOp", 53);
PyModule_AddIntConstant(m, "XorCompositeOp", 54);
PyModule_AddIntConstant(m, "DivideCompositeOp", 55);
PyModule_AddIntConstant(m, "DivideDstCompositeOp", 55);
PyModule_AddIntConstant(m, "DistortCompositeOp", 56);
PyModule_AddIntConstant(m, "BlurCompositeOp", 57);
PyModule_AddIntConstant(m, "PegtopLightCompositeOp", 58);
@ -226,6 +231,10 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "LinearDodgeCompositeOp", 61);
PyModule_AddIntConstant(m, "LinearBurnCompositeOp", 62);
PyModule_AddIntConstant(m, "MathematicsCompositeOp", 63);
PyModule_AddIntConstant(m, "DivideSrcCompositeOp", 64);
PyModule_AddIntConstant(m, "MinusSrcCompositeOp", 65);
PyModule_AddIntConstant(m, "DarkenIntensityCompositeOp", 66);
PyModule_AddIntConstant(m, "LightenIntensityCompositeOp", 67);
PyModule_AddIntConstant(m, "NoValue", 0);
PyModule_AddIntConstant(m, "XValue", 1);
PyModule_AddIntConstant(m, "XiValue", 1);
@ -250,6 +259,7 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "CorrelateNormalizeValue", 65536);
PyModule_AddIntConstant(m, "AreaValue", 131072);
PyModule_AddIntConstant(m, "DecimalValue", 262144);
PyModule_AddIntConstant(m, "SeparatorValue", 524288);
PyModule_AddIntConstant(m, "AllValues", 2147483647);
PyModule_AddIntConstant(m, "UndefinedGravity", 0);
PyModule_AddIntConstant(m, "ForgetGravity", 0);
@ -286,4 +296,18 @@ static void magick_add_module_constants(PyObject *m) {
PyModule_AddIntConstant(m, "Rec709YCbCrColorspace", 20);
PyModule_AddIntConstant(m, "LogColorspace", 21);
PyModule_AddIntConstant(m, "CMYColorspace", 22);
PyModule_AddIntConstant(m, "LuvColorspace", 23);
PyModule_AddIntConstant(m, "HCLColorspace", 24);
PyModule_AddIntConstant(m, "LCHColorspace", 25);
PyModule_AddIntConstant(m, "LMSColorspace", 26);
PyModule_AddIntConstant(m, "UndefinedMetric", 0);
PyModule_AddIntConstant(m, "AbsoluteErrorMetric", 1);
PyModule_AddIntConstant(m, "MeanAbsoluteErrorMetric", 2);
PyModule_AddIntConstant(m, "MeanErrorPerPixelMetric", 3);
PyModule_AddIntConstant(m, "MeanSquaredErrorMetric", 4);
PyModule_AddIntConstant(m, "PeakAbsoluteErrorMetric", 5);
PyModule_AddIntConstant(m, "PeakSignalToNoiseRatioMetric", 6);
PyModule_AddIntConstant(m, "RootMeanSquaredErrorMetric", 7);
PyModule_AddIntConstant(m, "NormalizedCrossCorrelationErrorMetric", 8);
PyModule_AddIntConstant(m, "FuzzErrorMetric", 9);
}