mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	Merge pull request #1941 from uploadcare/cleanup-transforms
Cleanup transforms
This commit is contained in:
		
						commit
						ebd3c35de5
					
				
							
								
								
									
										89
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								PIL/Image.py
									
									
									
									
									
								
							|  | @ -30,6 +30,7 @@ from PIL import VERSION, PILLOW_VERSION, _plugins | |||
| 
 | ||||
| import logging | ||||
| import warnings | ||||
| import math | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
|  | @ -995,8 +996,7 @@ class Image(object): | |||
|             im = self.im.convert("P", 1, palette.im) | ||||
|             return self._makeself(im) | ||||
| 
 | ||||
|         im = self.im.quantize(colors, method, kmeans) | ||||
|         return self._new(im) | ||||
|         return self._new(self.im.quantize(colors, method, kmeans)) | ||||
| 
 | ||||
|     def copy(self): | ||||
|         """ | ||||
|  | @ -1007,8 +1007,7 @@ class Image(object): | |||
|         :returns: An :py:class:`~PIL.Image.Image` object. | ||||
|         """ | ||||
|         self.load() | ||||
|         im = self.im.copy() | ||||
|         return self._new(im) | ||||
|         return self._new(self.im.copy()) | ||||
| 
 | ||||
|     __copy__ = copy | ||||
| 
 | ||||
|  | @ -1571,20 +1570,31 @@ class Image(object): | |||
|         :returns: An :py:class:`~PIL.Image.Image` object. | ||||
|         """ | ||||
| 
 | ||||
|         angle = angle % 360.0 | ||||
| 
 | ||||
|         # Fast paths regardless of filter | ||||
|         if angle == 0: | ||||
|             return self._new(self.im) | ||||
|         if angle == 180: | ||||
|             return self.transpose(ROTATE_180) | ||||
|         if angle == 90 and expand: | ||||
|             return self.transpose(ROTATE_90) | ||||
|         if angle == 270 and expand: | ||||
|             return self.transpose(ROTATE_270) | ||||
| 
 | ||||
|         angle = - math.radians(angle) | ||||
|         matrix = [ | ||||
|             round(math.cos(angle), 15), round(math.sin(angle), 15), 0.0, | ||||
|             round(-math.sin(angle), 15), round(math.cos(angle), 15), 0.0 | ||||
|             ] | ||||
| 
 | ||||
|         def transform(x, y, matrix=matrix): | ||||
|             (a, b, c, d, e, f) = matrix | ||||
|             return a*x + b*y + c, d*x + e*y + f | ||||
| 
 | ||||
|         w, h = self.size | ||||
|         if expand: | ||||
|             import math | ||||
|             angle = -angle * math.pi / 180 | ||||
|             matrix = [ | ||||
|                 math.cos(angle), math.sin(angle), 0.0, | ||||
|                 -math.sin(angle), math.cos(angle), 0.0 | ||||
|                 ] | ||||
| 
 | ||||
|             def transform(x, y, matrix=matrix): | ||||
|                 (a, b, c, d, e, f) = matrix | ||||
|                 return a*x + b*y + c, d*x + e*y + f | ||||
| 
 | ||||
|             # calculate output size | ||||
|             w, h = self.size | ||||
|             xx = [] | ||||
|             yy = [] | ||||
|             for x, y in ((0, 0), (w, 0), (w, h), (0, h)): | ||||
|  | @ -1594,22 +1604,12 @@ class Image(object): | |||
|             w = int(math.ceil(max(xx)) - math.floor(min(xx))) | ||||
|             h = int(math.ceil(max(yy)) - math.floor(min(yy))) | ||||
| 
 | ||||
|             # adjust center | ||||
|             x, y = transform(w / 2.0, h / 2.0) | ||||
|             matrix[2] = self.size[0] / 2.0 - x | ||||
|             matrix[5] = self.size[1] / 2.0 - y | ||||
|         # adjust center | ||||
|         x, y = transform(w / 2.0, h / 2.0) | ||||
|         matrix[2] = self.size[0] / 2.0 - x | ||||
|         matrix[5] = self.size[1] / 2.0 - y | ||||
| 
 | ||||
|             return self.transform((w, h), AFFINE, matrix, resample) | ||||
| 
 | ||||
|         if resample not in (NEAREST, BILINEAR, BICUBIC): | ||||
|             raise ValueError("unknown resampling filter") | ||||
| 
 | ||||
|         self.load() | ||||
| 
 | ||||
|         if self.mode in ("1", "P"): | ||||
|             resample = NEAREST | ||||
| 
 | ||||
|         return self._new(self.im.rotate(angle, resample, expand)) | ||||
|         return self.transform((w, h), AFFINE, matrix, resample) | ||||
| 
 | ||||
|     def save(self, fp, format=None, **params): | ||||
|         """ | ||||
|  | @ -1845,9 +1845,11 @@ class Image(object): | |||
| 
 | ||||
|         if isinstance(method, ImageTransformHandler): | ||||
|             return method.transform(size, self, resample=resample, fill=fill) | ||||
| 
 | ||||
|         if hasattr(method, "getdata"): | ||||
|             # compatibility w. old-style transform objects | ||||
|             method, data = method.getdata() | ||||
| 
 | ||||
|         if data is None: | ||||
|             raise ValueError("missing method data") | ||||
| 
 | ||||
|  | @ -1863,28 +1865,23 @@ class Image(object): | |||
| 
 | ||||
|     def __transformer(self, box, image, method, data, | ||||
|                       resample=NEAREST, fill=1): | ||||
| 
 | ||||
|         # FIXME: this should be turned into a lazy operation (?) | ||||
| 
 | ||||
|         w = box[2]-box[0] | ||||
|         h = box[3]-box[1] | ||||
|         w = box[2] - box[0] | ||||
|         h = box[3] - box[1] | ||||
| 
 | ||||
|         if method == AFFINE: | ||||
|             # change argument order to match implementation | ||||
|             data = (data[2], data[0], data[1], | ||||
|                     data[5], data[3], data[4]) | ||||
|             data = data[0:6] | ||||
| 
 | ||||
|         elif method == EXTENT: | ||||
|             # convert extent to an affine transform | ||||
|             x0, y0, x1, y1 = data | ||||
|             xs = float(x1 - x0) / w | ||||
|             ys = float(y1 - y0) / h | ||||
|             method = AFFINE | ||||
|             data = (x0 + xs/2, xs, 0, y0 + ys/2, 0, ys) | ||||
|             data = (xs, 0, x0 + xs/2, 0, ys, y0 + ys/2) | ||||
| 
 | ||||
|         elif method == PERSPECTIVE: | ||||
|             # change argument order to match implementation | ||||
|             data = (data[2], data[0], data[1], | ||||
|                     data[5], data[3], data[4], | ||||
|                     data[6], data[7]) | ||||
|             data = data[0:8] | ||||
| 
 | ||||
|         elif method == QUAD: | ||||
|             # quadrilateral warp.  data specifies the four corners | ||||
|             # given as NW, SW, SE, and NE. | ||||
|  | @ -1899,6 +1896,7 @@ class Image(object): | |||
|                     (se[0]-sw[0]-ne[0]+x0)*As*At, | ||||
|                     y0, (ne[1]-y0)*As, (sw[1]-y0)*At, | ||||
|                     (se[1]-sw[1]-ne[1]+y0)*As*At) | ||||
| 
 | ||||
|         else: | ||||
|             raise ValueError("unknown transformation method") | ||||
| 
 | ||||
|  | @ -1935,8 +1933,7 @@ class Image(object): | |||
|         :param distance: Distance to spread pixels. | ||||
|         """ | ||||
|         self.load() | ||||
|         im = self.im.effect_spread(distance) | ||||
|         return self._new(im) | ||||
|         return self._new(self.im.effect_spread(distance)) | ||||
| 
 | ||||
|     def toqimage(self): | ||||
|         """Returns a QImage copy of this image""" | ||||
|  |  | |||
							
								
								
									
										88
									
								
								_imaging.c
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								_imaging.c
									
									
									
									
									
								
							|  | @ -1544,17 +1544,17 @@ _resize(ImagingObject* self, PyObject* args) | |||
|     if (imIn->xsize == xsize && imIn->ysize == ysize) { | ||||
|         imOut = ImagingCopy(imIn); | ||||
|     } | ||||
|     else if ( ! filter) { | ||||
|     else if (filter == IMAGING_TRANSFORM_NEAREST) { | ||||
|         double a[6]; | ||||
| 
 | ||||
|         memset(a, 0, sizeof a); | ||||
|         a[1] = (double) imIn->xsize / xsize; | ||||
|         a[5] = (double) imIn->ysize / ysize; | ||||
|         a[0] = (double) imIn->xsize / xsize; | ||||
|         a[4] = (double) imIn->ysize / ysize; | ||||
| 
 | ||||
|         imOut = ImagingNew(imIn->mode, xsize, ysize); | ||||
| 
 | ||||
|         imOut = ImagingTransformAffine( | ||||
|             imOut, imIn, | ||||
|         imOut = ImagingTransform( | ||||
|             imOut, imIn, IMAGING_TRANSFORM_AFFINE, | ||||
|             0, 0, xsize, ysize, | ||||
|             a, filter, 1); | ||||
|     } | ||||
|  | @ -1565,55 +1565,6 @@ _resize(ImagingObject* self, PyObject* args) | |||
|     return PyImagingNew(imOut); | ||||
| } | ||||
| 
 | ||||
| static PyObject* | ||||
| _rotate(ImagingObject* self, PyObject* args) | ||||
| { | ||||
|     Imaging imOut; | ||||
|     Imaging imIn; | ||||
| 
 | ||||
|     double theta; | ||||
|     int filter = IMAGING_TRANSFORM_NEAREST; | ||||
|     int expand; | ||||
|     if (!PyArg_ParseTuple(args, "d|i|i", &theta, &filter, &expand)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     imIn = self->image; | ||||
| 
 | ||||
|     theta = fmod(theta, 360.0); | ||||
|     if (theta < 0.0) | ||||
|     theta += 360; | ||||
| 
 | ||||
|     if (filter && imIn->type != IMAGING_TYPE_SPECIAL) { | ||||
|         /* Rotate with resampling filter */ | ||||
|         imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     (void) ImagingRotate(imOut, imIn, theta, filter); | ||||
|     } else if ((theta == 90.0 || theta == 270.0) | ||||
|             && (expand || imIn->xsize == imIn->ysize)) { | ||||
|         /* Use fast version */ | ||||
|         imOut = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|         if (imOut) { | ||||
|             if (theta == 90.0) | ||||
|                 (void) ImagingRotate90(imOut, imIn); | ||||
|             else | ||||
|                 (void) ImagingRotate270(imOut, imIn); | ||||
|         } | ||||
|     } else { | ||||
|         imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|         if (imOut) { | ||||
|             if (theta == 0.0) | ||||
|                 /* No rotation: simply copy the input image */ | ||||
|                 (void) ImagingCopy2(imOut, imIn); | ||||
|             else if (theta == 180.0) | ||||
|                 /* Use fast version */ | ||||
|                 (void) ImagingRotate180(imOut, imIn); | ||||
|             else | ||||
|                 /* Use ordinary version */ | ||||
|                 (void) ImagingRotate(imOut, imIn, theta, 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return PyImagingNew(imOut); | ||||
| } | ||||
| 
 | ||||
| #define IS_RGB(mode)\ | ||||
|     (!strcmp(mode, "RGB") || !strcmp(mode, "RGBA") || !strcmp(mode, "RGBX")) | ||||
|  | @ -1662,7 +1613,6 @@ _transform2(ImagingObject* self, PyObject* args) | |||
| { | ||||
|     static const char* wrong_number = "wrong number of matrix entries"; | ||||
| 
 | ||||
|     Imaging imIn; | ||||
|     Imaging imOut; | ||||
|     int n; | ||||
|     double *a; | ||||
|  | @ -1698,30 +1648,9 @@ _transform2(ImagingObject* self, PyObject* args) | |||
|     if (!a) | ||||
|         return NULL; | ||||
| 
 | ||||
|     imOut = self->image; | ||||
|     imIn = imagep->image; | ||||
| 
 | ||||
|     /* FIXME: move transform dispatcher into libImaging */ | ||||
| 
 | ||||
|     switch (method) { | ||||
|     case IMAGING_TRANSFORM_AFFINE: | ||||
|         imOut = ImagingTransformAffine( | ||||
|             imOut, imIn, x0, y0, x1, y1, a, filter, 1 | ||||
|             ); | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_PERSPECTIVE: | ||||
|         imOut = ImagingTransformPerspective( | ||||
|             imOut, imIn, x0, y0, x1, y1, a, filter, 1 | ||||
|             ); | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_QUAD: | ||||
|         imOut = ImagingTransformQuad( | ||||
|             imOut, imIn, x0, y0, x1, y1, a, filter, 1 | ||||
|             ); | ||||
|         break; | ||||
|     default: | ||||
|         (void) ImagingError_ValueError("bad transform method"); | ||||
|     } | ||||
|     imOut = ImagingTransform( | ||||
|         self->image, imagep->image, method, | ||||
|         x0, y0, x1, y1, a, filter, 1); | ||||
| 
 | ||||
|     free(a); | ||||
| 
 | ||||
|  | @ -3048,7 +2977,6 @@ static struct PyMethodDef methods[] = { | |||
|     // There were two methods for image resize before.
 | ||||
|     // Starting from Pillow 2.7.0 stretch is depreciated.
 | ||||
|     {"stretch", (PyCFunction)_resize, 1}, | ||||
|     {"rotate", (PyCFunction)_rotate, 1}, | ||||
|     {"transpose", (PyCFunction)_transpose, 1}, | ||||
|     {"transform2", (PyCFunction)_transform2, 1}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,35 +1,5 @@ | |||
| /*
 | ||||
|  * The Python Imaging Library | ||||
|  * $Id$ | ||||
|  * | ||||
|  * the imaging geometry methods | ||||
|  * | ||||
|  * history: | ||||
|  * 1995-06-15 fl  Created | ||||
|  * 1996-04-15 fl  Changed origin | ||||
|  * 1996-05-18 fl  Fixed rotate90/270 for rectangular images | ||||
|  * 1996-05-27 fl  Added general purpose transform | ||||
|  * 1996-11-22 fl  Don't crash when resizing from outside source image | ||||
|  * 1997-08-09 fl  Fixed rounding error in resize | ||||
|  * 1998-09-21 fl  Incorporated transformation patches (from Zircon #2) | ||||
|  * 1998-09-22 fl  Added bounding box to transform engines | ||||
|  * 1999-02-03 fl  Fixed bicubic filtering for RGB images | ||||
|  * 1999-02-16 fl  Added fixed-point version of affine transform | ||||
|  * 2001-03-28 fl  Fixed transform(EXTENT) for xoffset < 0 | ||||
|  * 2003-03-10 fl  Compiler tweaks | ||||
|  * 2004-09-19 fl  Fixed bilinear/bicubic filtering of LA images | ||||
|  * | ||||
|  * Copyright (c) 1997-2003 by Secret Labs AB | ||||
|  * Copyright (c) 1995-1997 by Fredrik Lundh | ||||
|  * | ||||
|  * See the README file for information on usage and redistribution. | ||||
|  */ | ||||
| 
 | ||||
| #include "Imaging.h" | ||||
| 
 | ||||
| /* Undef if you don't need resampling filters */ | ||||
| #define WITH_FILTERS | ||||
| 
 | ||||
| /* For large images rotation is an inefficient operation in terms of CPU cache.
 | ||||
|    One row in the source image affects each column in destination. | ||||
|    Rotating in chunks that fit in the cache can speed up rotation | ||||
|  | @ -72,6 +42,8 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef FLIP_HORIZ | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  | @ -91,7 +63,7 @@ ImagingFlipTopBottom(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
| 
 | ||||
|     yr = imIn->ysize-1; | ||||
|     yr = imIn->ysize - 1; | ||||
|     for (y = 0; y < imIn->ysize; y++, yr--) | ||||
|         memcpy(imOut->image[yr], imIn->image[y], imIn->linesize); | ||||
| 
 | ||||
|  | @ -137,6 +109,8 @@ ImagingRotate90(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef ROTATE_90 | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  | @ -152,6 +126,8 @@ ImagingTranspose(Imaging imOut, Imaging imIn) | |||
|     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) | ||||
|         return (Imaging) ImagingError_Mismatch(); | ||||
| 
 | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
| #define TRANSPOSE(image) \ | ||||
|     for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { \ | ||||
|         for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { \ | ||||
|  | @ -165,34 +141,21 @@ ImagingTranspose(Imaging imOut, Imaging imIn) | |||
|         } \ | ||||
|     } | ||||
| 
 | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
|      | ||||
|     if (imIn->image8) | ||||
|         TRANSPOSE(image8) | ||||
|     else | ||||
|         TRANSPOSE(image32) | ||||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef TRANSPOSE | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Imaging | ||||
| ImagingTransposeToNew(Imaging imIn) | ||||
| { | ||||
|     Imaging imTemp = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|     if ( ! imTemp) | ||||
|         return NULL; | ||||
| 
 | ||||
|     if ( ! ImagingTranspose(imTemp, imIn)) { | ||||
|         ImagingDelete(imTemp); | ||||
|         return NULL; | ||||
|     } | ||||
|     return imTemp; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Imaging | ||||
| ImagingRotate180(Imaging imOut, Imaging imIn) | ||||
| { | ||||
|  | @ -206,8 +169,6 @@ ImagingRotate180(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
|     yr = imIn->ysize-1; | ||||
| 
 | ||||
| #define ROTATE_180(image)\ | ||||
|     for (y = 0; y < imIn->ysize; y++, yr--) {\ | ||||
|         xr = imIn->xsize-1;\ | ||||
|  | @ -217,6 +178,7 @@ ImagingRotate180(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
| 
 | ||||
|     yr = imIn->ysize-1; | ||||
|     if (imIn->image8) | ||||
|         ROTATE_180(image8) | ||||
|     else | ||||
|  | @ -224,6 +186,8 @@ ImagingRotate180(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef ROTATE_180 | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  | @ -264,6 +228,8 @@ ImagingRotate270(Imaging imOut, Imaging imIn) | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef ROTATE_270 | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  | @ -284,8 +250,8 @@ affine_transform(double* xin, double* yin, int x, int y, void* data) | |||
|     double a0 = a[0]; double a1 = a[1]; double a2 = a[2]; | ||||
|     double a3 = a[3]; double a4 = a[4]; double a5 = a[5]; | ||||
| 
 | ||||
|     xin[0] = a0 + a1*x + a2*y; | ||||
|     yin[0] = a3 + a4*x + a5*y; | ||||
|     xin[0] = a0*x + a1*y + a2; | ||||
|     yin[0] = a3*x + a4*y + a5; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
|  | @ -298,8 +264,8 @@ perspective_transform(double* xin, double* yin, int x, int y, void* data) | |||
|     double a3 = a[3]; double a4 = a[4]; double a5 = a[5]; | ||||
|     double a6 = a[6]; double a7 = a[7]; | ||||
| 
 | ||||
|     xin[0] = (a0 + a1*x + a2*y) / (a6*x + a7*y + 1); | ||||
|     yin[0] = (a3 + a4*x + a5*y) / (a6*x + a7*y + 1); | ||||
|     xin[0] = (a0*x + a1*y + a2) / (a6*x + a7*y + 1); | ||||
|     yin[0] = (a3*x + a4*y + a5) / (a6*x + a7*y + 1); | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
|  | @ -321,10 +287,8 @@ quad_transform(double* xin, double* yin, int x, int y, void* data) | |||
| 
 | ||||
| /* transform filters (ImagingTransformFilter) */ | ||||
| 
 | ||||
| #ifdef WITH_FILTERS | ||||
| 
 | ||||
| static int | ||||
| nearest_filter8(void* out, Imaging im, double xin, double yin, void* data) | ||||
| nearest_filter8(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     int x = COORD(xin); | ||||
|     int y = COORD(yin); | ||||
|  | @ -335,7 +299,7 @@ nearest_filter8(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| nearest_filter16(void* out, Imaging im, double xin, double yin, void* data) | ||||
| nearest_filter16(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     int x = COORD(xin); | ||||
|     int y = COORD(yin); | ||||
|  | @ -346,7 +310,7 @@ nearest_filter16(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| nearest_filter32(void* out, Imaging im, double xin, double yin, void* data) | ||||
| nearest_filter32(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     int x = COORD(xin); | ||||
|     int y = COORD(yin); | ||||
|  | @ -391,7 +355,7 @@ nearest_filter32(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bilinear_filter8(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bilinear_filter8(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BILINEAR_HEAD(UINT8); | ||||
|     BILINEAR_BODY(UINT8, im->image8, 1, 0); | ||||
|  | @ -400,7 +364,7 @@ bilinear_filter8(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bilinear_filter32I(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bilinear_filter32I(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BILINEAR_HEAD(INT32); | ||||
|     BILINEAR_BODY(INT32, im->image32, 1, 0); | ||||
|  | @ -409,7 +373,7 @@ bilinear_filter32I(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bilinear_filter32F(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bilinear_filter32F(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BILINEAR_HEAD(FLOAT32); | ||||
|     BILINEAR_BODY(FLOAT32, im->image32, 1, 0); | ||||
|  | @ -418,7 +382,7 @@ bilinear_filter32F(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bilinear_filter32LA(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bilinear_filter32LA(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BILINEAR_HEAD(UINT8); | ||||
|     BILINEAR_BODY(UINT8, im->image, 4, 0); | ||||
|  | @ -431,7 +395,7 @@ bilinear_filter32LA(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bilinear_filter32RGB(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bilinear_filter32RGB(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     int b; | ||||
|     BILINEAR_HEAD(UINT8); | ||||
|  | @ -442,6 +406,10 @@ bilinear_filter32RGB(void* out, Imaging im, double xin, double yin, void* data) | |||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #undef BILINEAR | ||||
| #undef BILINEAR_HEAD | ||||
| #undef BILINEAR_BODY | ||||
| 
 | ||||
| #define BICUBIC(v, v1, v2, v3, v4, d) {\ | ||||
|     double p1 = v2;\ | ||||
|     double p2 = -v1 + v3;\ | ||||
|  | @ -494,7 +462,7 @@ bilinear_filter32RGB(void* out, Imaging im, double xin, double yin, void* data) | |||
| 
 | ||||
| 
 | ||||
| static int | ||||
| bicubic_filter8(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bicubic_filter8(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BICUBIC_HEAD(UINT8); | ||||
|     BICUBIC_BODY(UINT8, im->image8, 1, 0); | ||||
|  | @ -508,7 +476,7 @@ bicubic_filter8(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bicubic_filter32I(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bicubic_filter32I(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BICUBIC_HEAD(INT32); | ||||
|     BICUBIC_BODY(INT32, im->image32, 1, 0); | ||||
|  | @ -517,7 +485,7 @@ bicubic_filter32I(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bicubic_filter32F(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bicubic_filter32F(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BICUBIC_HEAD(FLOAT32); | ||||
|     BICUBIC_BODY(FLOAT32, im->image32, 1, 0); | ||||
|  | @ -526,7 +494,7 @@ bicubic_filter32F(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bicubic_filter32LA(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bicubic_filter32LA(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     BICUBIC_HEAD(UINT8); | ||||
|     BICUBIC_BODY(UINT8, im->image, 4, 0); | ||||
|  | @ -554,7 +522,7 @@ bicubic_filter32LA(void* out, Imaging im, double xin, double yin, void* data) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| bicubic_filter32RGB(void* out, Imaging im, double xin, double yin, void* data) | ||||
| bicubic_filter32RGB(void* out, Imaging im, double xin, double yin) | ||||
| { | ||||
|     int b; | ||||
|     BICUBIC_HEAD(UINT8); | ||||
|  | @ -570,6 +538,10 @@ bicubic_filter32RGB(void* out, Imaging im, double xin, double yin, void* data) | |||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #undef BICUBIC | ||||
| #undef BICUBIC_HEAD | ||||
| #undef BICUBIC_BODY | ||||
| 
 | ||||
| static ImagingTransformFilter | ||||
| getfilter(Imaging im, int filterid) | ||||
| { | ||||
|  | @ -578,51 +550,51 @@ getfilter(Imaging im, int filterid) | |||
|         if (im->image8) | ||||
|             switch (im->type) { | ||||
|             case IMAGING_TYPE_UINT8: | ||||
|                 return (ImagingTransformFilter) nearest_filter8; | ||||
|                 return nearest_filter8; | ||||
|             case IMAGING_TYPE_SPECIAL: | ||||
|                 switch (im->pixelsize) { | ||||
|                 case 1: | ||||
|                     return (ImagingTransformFilter) nearest_filter8; | ||||
|                     return nearest_filter8; | ||||
|                 case 2: | ||||
|                     return (ImagingTransformFilter) nearest_filter16; | ||||
|                     return nearest_filter16; | ||||
|                 case 4: | ||||
|                     return (ImagingTransformFilter) nearest_filter32; | ||||
|                     return nearest_filter32; | ||||
|                 } | ||||
|             } | ||||
|         else | ||||
|             return (ImagingTransformFilter) nearest_filter32; | ||||
|             return nearest_filter32; | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_BILINEAR: | ||||
|         if (im->image8) | ||||
|             return (ImagingTransformFilter) bilinear_filter8; | ||||
|             return bilinear_filter8; | ||||
|         else if (im->image32) { | ||||
|             switch (im->type) { | ||||
|             case IMAGING_TYPE_UINT8: | ||||
|                 if (im->bands == 2) | ||||
|                     return (ImagingTransformFilter) bilinear_filter32LA; | ||||
|                     return bilinear_filter32LA; | ||||
|                 else | ||||
|                     return (ImagingTransformFilter) bilinear_filter32RGB; | ||||
|                     return bilinear_filter32RGB; | ||||
|             case IMAGING_TYPE_INT32: | ||||
|                 return (ImagingTransformFilter) bilinear_filter32I; | ||||
|                 return bilinear_filter32I; | ||||
|             case IMAGING_TYPE_FLOAT32: | ||||
|                 return (ImagingTransformFilter) bilinear_filter32F; | ||||
|                 return bilinear_filter32F; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_BICUBIC: | ||||
|         if (im->image8) | ||||
|             return (ImagingTransformFilter) bicubic_filter8; | ||||
|             return bicubic_filter8; | ||||
|         else if (im->image32) { | ||||
|             switch (im->type) { | ||||
|             case IMAGING_TYPE_UINT8: | ||||
|                 if (im->bands == 2) | ||||
|                     return (ImagingTransformFilter) bicubic_filter32LA; | ||||
|                     return bicubic_filter32LA; | ||||
|                 else | ||||
|                     return (ImagingTransformFilter) bicubic_filter32RGB; | ||||
|                     return bicubic_filter32RGB; | ||||
|             case IMAGING_TYPE_INT32: | ||||
|                 return (ImagingTransformFilter) bicubic_filter32I; | ||||
|                 return bicubic_filter32I; | ||||
|             case IMAGING_TYPE_FLOAT32: | ||||
|                 return (ImagingTransformFilter) bicubic_filter32F; | ||||
|                 return bicubic_filter32F; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|  | @ -631,18 +603,13 @@ getfilter(Imaging im, int filterid) | |||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| #define getfilter(im, id) NULL | ||||
| #endif | ||||
| 
 | ||||
| /* transformation engines */ | ||||
| 
 | ||||
| Imaging | ||||
| ImagingTransform( | ||||
| ImagingGenericTransform( | ||||
|     Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1, | ||||
|     ImagingTransformMap transform, void* transform_data, | ||||
|     ImagingTransformFilter filter, void* filter_data, | ||||
|     int fill) | ||||
|     int filterid, int fill) | ||||
| { | ||||
|     /* slow generic transformation.  use ImagingTransformAffine or
 | ||||
|        ImagingScaleAffine where possible. */ | ||||
|  | @ -652,6 +619,10 @@ ImagingTransform( | |||
|     char *out; | ||||
|     double xx, yy; | ||||
| 
 | ||||
|     ImagingTransformFilter filter = getfilter(imIn, filterid); | ||||
|     if (!filter) | ||||
|         return (Imaging) ImagingError_ValueError("bad filter number"); | ||||
| 
 | ||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) | ||||
|         return (Imaging) ImagingError_ModeError(); | ||||
| 
 | ||||
|  | @ -671,8 +642,8 @@ ImagingTransform( | |||
|     for (y = y0; y < y1; y++) { | ||||
|         out = imOut->image[y] + x0*imOut->pixelsize; | ||||
|         for (x = x0; x < x1; x++) { | ||||
|             if (!transform(&xx, &yy, x-x0, y-y0, transform_data) || | ||||
|                 !filter(out, imIn, xx, yy, filter_data)) { | ||||
|             if ( ! transform(&xx, &yy, x-x0, y-y0, transform_data) || | ||||
|                  ! filter(out, imIn, xx, yy)) { | ||||
|                 if (fill) | ||||
|                     memset(out, 0, imOut->pixelsize); | ||||
|             } | ||||
|  | @ -719,8 +690,8 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | |||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     xo = a[0]; | ||||
|     yo = a[3]; | ||||
|     xo = a[2]; | ||||
|     yo = a[5]; | ||||
| 
 | ||||
|     xmin = x1; | ||||
|     xmax = x0; | ||||
|  | @ -734,7 +705,7 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | |||
|                 xmin = x; | ||||
|             xintab[x] = xin; | ||||
|         } | ||||
|         xo += a[1]; | ||||
|         xo += a[0]; | ||||
|     } | ||||
| 
 | ||||
| #define AFFINE_SCALE(pixel, image)\ | ||||
|  | @ -749,7 +720,7 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | |||
|             for (x = xmin; x < xmax; x++)\ | ||||
|                 out[x] = in[xintab[x]];\ | ||||
|         }\ | ||||
|         yo += a[5];\ | ||||
|         yo += a[4];\ | ||||
|     } | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
|  | @ -762,6 +733,8 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef AFFINE_SCALE | ||||
| 
 | ||||
|     free(xintab); | ||||
| 
 | ||||
|     return imOut; | ||||
|  | @ -770,8 +743,8 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | |||
| static inline int | ||||
| check_fixed(double a[6], int x, int y) | ||||
| { | ||||
|     return (fabs(a[0] + x*a[1] + y*a[2]) < 32768.0 && | ||||
|             fabs(a[3] + x*a[4] + y*a[5]) < 32768.0); | ||||
|     return (fabs(x*a[0] + y*a[1] + a[2]) < 32768.0 && | ||||
|             fabs(x*a[3] + y*a[4] + a[5]) < 32768.0); | ||||
| } | ||||
| 
 | ||||
| static inline Imaging | ||||
|  | @ -782,6 +755,7 @@ affine_fixed(Imaging imOut, Imaging imIn, | |||
|     /* affine transform, nearest neighbour resampling, fixed point
 | ||||
|        arithmetics */ | ||||
| 
 | ||||
|     ImagingSectionCookie cookie; | ||||
|     int x, y; | ||||
|     int xin, yin; | ||||
|     int xsize, ysize; | ||||
|  | @ -799,11 +773,13 @@ affine_fixed(Imaging imOut, Imaging imIn, | |||
|     a0 = FIX(a[0]); a1 = FIX(a[1]); a2 = FIX(a[2]); | ||||
|     a3 = FIX(a[3]); a4 = FIX(a[4]); a5 = FIX(a[5]); | ||||
| 
 | ||||
| #undef FIX | ||||
| 
 | ||||
| #define AFFINE_TRANSFORM_FIXED(pixel, image)\ | ||||
|     for (y = y0; y < y1; y++) {\ | ||||
|         pixel *out;\ | ||||
|         xx = a0;\ | ||||
|         yy = a3;\ | ||||
|         xx = a2;\ | ||||
|         yy = a5;\ | ||||
|         out = imOut->image[y];\ | ||||
|         if (fill && x1 > x0)\ | ||||
|             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ | ||||
|  | @ -814,18 +790,24 @@ affine_fixed(Imaging imOut, Imaging imIn, | |||
|                 if (yin >= 0 && yin < ysize)\ | ||||
|                     *out = imIn->image[yin][xin];\ | ||||
|             }\ | ||||
|             xx += a1;\ | ||||
|             yy += a4;\ | ||||
|             xx += a0;\ | ||||
|             yy += a3;\ | ||||
|         }\ | ||||
|         a0 += a2;\ | ||||
|         a3 += a5;\ | ||||
|         a2 += a1;\ | ||||
|         a5 += a4;\ | ||||
|     } | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
| 
 | ||||
|     if (imIn->image8) | ||||
|         AFFINE_TRANSFORM_FIXED(UINT8, image8) | ||||
|     else | ||||
|         AFFINE_TRANSFORM_FIXED(INT32, image32) | ||||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef AFFINE_TRANSFORM_FIXED | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  | @ -845,18 +827,14 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | |||
|     double xo, yo; | ||||
| 
 | ||||
|     if (filterid || imIn->type == IMAGING_TYPE_SPECIAL) { | ||||
|         /* Filtered transform */ | ||||
|         ImagingTransformFilter filter = getfilter(imIn, filterid); | ||||
|         if (!filter) | ||||
|             return (Imaging) ImagingError_ValueError("unknown filter"); | ||||
|         return ImagingTransform( | ||||
|         return ImagingGenericTransform( | ||||
|             imOut, imIn, | ||||
|             x0, y0, x1, y1, | ||||
|             affine_transform, a, | ||||
|             filter, NULL, fill); | ||||
|             filterid, fill); | ||||
|     } | ||||
| 
 | ||||
|     if (a[2] == 0 && a[4] == 0) | ||||
|     if (a[1] == 0 && a[3] == 0) | ||||
|         /* Scaling */ | ||||
|         return ImagingScaleAffine(imOut, imIn, x0, y0, x1, y1, a, fill); | ||||
| 
 | ||||
|  | @ -872,8 +850,6 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | |||
|     if (y1 > imOut->ysize) | ||||
|         y1 = imOut->ysize; | ||||
| 
 | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
|     /* translate all four corners to check if they are within the
 | ||||
|        range that can be represented by the fixed point arithmetics */ | ||||
| 
 | ||||
|  | @ -884,12 +860,14 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | |||
|     /* FIXME: cannot really think of any reasonable case when the
 | ||||
|        following code is used.  maybe we should fall back on the slow | ||||
|        generic transform engine in this case? */ | ||||
|      | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
|     xsize = (int) imIn->xsize; | ||||
|     ysize = (int) imIn->ysize; | ||||
| 
 | ||||
|     xo = a[0]; | ||||
|     yo = a[3]; | ||||
|     xo = a[2]; | ||||
|     yo = a[5]; | ||||
| 
 | ||||
| #define AFFINE_TRANSFORM(pixel, image)\ | ||||
|     for (y = y0; y < y1; y++) {\ | ||||
|  | @ -906,11 +884,11 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | |||
|                 if (yin >= 0 && yin < ysize)\ | ||||
|                     *out = imIn->image[yin][xin];\ | ||||
|             }\ | ||||
|             xx += a[1];\ | ||||
|             yy += a[4];\ | ||||
|             xx += a[0];\ | ||||
|             yy += a[3];\ | ||||
|         }\ | ||||
|         xo += a[2];\ | ||||
|         yo += a[5];\ | ||||
|         xo += a[1];\ | ||||
|         yo += a[4];\ | ||||
|     } | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
|  | @ -922,70 +900,35 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
| #undef AFFINE_TRANSFORM | ||||
| 
 | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingTransformPerspective(Imaging imOut, Imaging imIn, | ||||
|                             int x0, int y0, int x1, int y1, | ||||
|                             double a[8], int filterid, int fill) | ||||
| ImagingTransform(Imaging imOut, Imaging imIn, int method, | ||||
|                  int x0, int y0, int x1, int y1, | ||||
|                  double a[8], int filterid, int fill) | ||||
| { | ||||
|     ImagingTransformFilter filter = getfilter(imIn, filterid); | ||||
|     if (!filter) | ||||
|         return (Imaging) ImagingError_ValueError("bad filter number"); | ||||
|     ImagingTransformMap transform; | ||||
| 
 | ||||
|     return ImagingTransform( | ||||
|     switch(method) { | ||||
|     case IMAGING_TRANSFORM_AFFINE: | ||||
|         return ImagingTransformAffine( | ||||
|             imOut, imIn, x0, y0, x1, y1, a, filterid, fill); | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_PERSPECTIVE: | ||||
|         transform = perspective_transform; | ||||
|         break; | ||||
|     case IMAGING_TRANSFORM_QUAD: | ||||
|         transform = quad_transform; | ||||
|         break; | ||||
|     default: | ||||
|         return (Imaging) ImagingError_ValueError("bad transform method"); | ||||
|     } | ||||
| 
 | ||||
|     return ImagingGenericTransform( | ||||
|         imOut, imIn, | ||||
|         x0, y0, x1, y1, | ||||
|         perspective_transform, a, | ||||
|         filter, NULL, | ||||
|         fill); | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingTransformQuad(Imaging imOut, Imaging imIn, | ||||
|                      int x0, int y0, int x1, int y1, | ||||
|                      double a[8], int filterid, int fill) | ||||
| { | ||||
|     ImagingTransformFilter filter = getfilter(imIn, filterid); | ||||
|     if (!filter) | ||||
|         return (Imaging) ImagingError_ValueError("bad filter number"); | ||||
| 
 | ||||
|     return ImagingTransform( | ||||
|         imOut, imIn, | ||||
|         x0, y0, x1, y1, | ||||
|         quad_transform, a, | ||||
|         filter, NULL, | ||||
|         fill); | ||||
| } | ||||
| 
 | ||||
| /* -------------------------------------------------------------------- */ | ||||
| /* Convenience functions */ | ||||
| 
 | ||||
| Imaging | ||||
| ImagingRotate(Imaging imOut, Imaging imIn, double theta, int filterid) | ||||
| { | ||||
|     int xsize, ysize; | ||||
|     double sintheta, costheta; | ||||
|     double a[6]; | ||||
| 
 | ||||
|     /* Setup an affine transform to rotate around the image center */ | ||||
|     theta = -theta * M_PI / 180.0; | ||||
|     sintheta = sin(theta); | ||||
|     costheta = cos(theta); | ||||
| 
 | ||||
|     xsize = imOut->xsize; | ||||
|     ysize = imOut->ysize; | ||||
| 
 | ||||
|     a[0] = -costheta * xsize/2 - sintheta * ysize/2 + xsize/2; | ||||
|     a[1] = costheta; | ||||
|     a[2] = sintheta; | ||||
|     a[3] = sintheta * xsize/2 - costheta * ysize/2 + ysize/2; | ||||
|     a[4] = -sintheta; | ||||
|     a[5] = costheta; | ||||
| 
 | ||||
|     return ImagingTransformAffine( | ||||
|         imOut, imIn, | ||||
|         0, 0, imOut->xsize, imOut->ysize, | ||||
|         a, filterid, 1); | ||||
|         transform, a, filterid, fill); | ||||
| } | ||||
|  |  | |||
|  | @ -236,8 +236,7 @@ extern void ImagingError_Clear(void); | |||
| typedef int (*ImagingTransformMap)(double* X, double* Y, | ||||
|                                    int x, int y, void* data); | ||||
| typedef int (*ImagingTransformFilter)(void* out, Imaging im, | ||||
|                                       double x, double y, | ||||
|                                       void* data); | ||||
|                                       double x, double y); | ||||
| 
 | ||||
| /* Image Manipulation Methods */ | ||||
| /* -------------------------- */ | ||||
|  | @ -286,28 +285,14 @@ extern Imaging ImagingPointTransform( | |||
|     Imaging imIn, double scale, double offset); | ||||
| extern Imaging ImagingPutBand(Imaging im, Imaging imIn, int band); | ||||
| extern Imaging ImagingRankFilter(Imaging im, int size, int rank); | ||||
| extern Imaging ImagingRotate( | ||||
|     Imaging imOut, Imaging imIn, double theta, int filter); | ||||
| extern Imaging ImagingRotate90(Imaging imOut, Imaging imIn); | ||||
| extern Imaging ImagingRotate180(Imaging imOut, Imaging imIn); | ||||
| extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn); | ||||
| extern Imaging ImagingResample(Imaging imIn, int xsize, int ysize, int filter); | ||||
| extern Imaging ImagingTranspose(Imaging imOut, Imaging imIn); | ||||
| extern Imaging ImagingTransposeToNew(Imaging imIn); | ||||
| extern Imaging ImagingTransformPerspective( | ||||
|     Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1, | ||||
|     double a[8], int filter, int fill); | ||||
| extern Imaging ImagingTransformAffine( | ||||
|     Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1, | ||||
|     double a[6], int filter, int fill); | ||||
| extern Imaging ImagingTransformQuad( | ||||
|     Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1, | ||||
|     double a[8], int filter, int fill); | ||||
| extern Imaging ImagingTransform( | ||||
|     Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1, | ||||
|     ImagingTransformMap transform, void* transform_data, | ||||
|     ImagingTransformFilter filter, void* filter_data, | ||||
|     int fill); | ||||
|     Imaging imOut, Imaging imIn, int method, int x0, int y0, int x1, int y1, | ||||
|     double *a, int filter, int fill); | ||||
| extern Imaging ImagingUnsharpMask( | ||||
|     Imaging imOut, Imaging im, float radius, int percent, int threshold); | ||||
| extern Imaging ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n); | ||||
|  | @ -338,12 +323,6 @@ extern Imaging ImagingChopXor(Imaging imIn1, Imaging imIn2); | |||
| extern void ImagingCrack(Imaging im, int x0, int y0); | ||||
| 
 | ||||
| /* Graphics */ | ||||
| struct ImagingAffineMatrixInstance { | ||||
|     float a[9]; | ||||
| }; | ||||
| 
 | ||||
| typedef struct ImagingAffineMatrixInstance *ImagingAffineMatrix; | ||||
| 
 | ||||
| extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1, | ||||
|                           float start, float end, const void* ink, int op); | ||||
| extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user