1 module dmagick.c.distort;
2 
3 import dmagick.c.exception;
4 import dmagick.c.geometry;
5 import dmagick.c.image;
6 import dmagick.c.magickType;
7 import dmagick.c.magickVersion;
8 
9 extern(C)
10 {
11 	version(D_Ddoc)
12 	{
13 		/**
14 		 * The distortion method to use when distorting an image.
15 		 */
16 		enum DistortImageMethod
17 		{
18 			/** */
19 			UndefinedDistortion,
20 
21 			/**
22 			 * Distort the image linearly by moving a list of at least 3 or
23 			 * more sets of control points (as defined below). Ideally 3 sets
24 			 * or 12 floating point values are given allowing the image to
25 			 * be linearly scaled, rotated, sheared, and translated, according
26 			 * to those three points. See also the related AffineProjection
27 			 * and ScaleRotateTranslateDistortion distortions. 
28 			 * 
29 			 * More than 3 sets given control point pairs (12 numbers) is least
30 			 * squares fitted to best match a lineary affine distortion. If only
31 			 * 2 control point pairs (8 numbers) are given a two point image
32 			 * translation rotation and scaling is performed, without any possible
33 			 * shearing, flipping or changes in aspect ratio to the resulting image.
34 			 * If only one control point pair is provides the image is only
35 			 * translated, (which may be a floating point non-integer translation). 
36 			 * 
37 			 * This distortion does not include any form of perspective distortion.
38 			 */
39 			AffineDistortion,
40 
41 			/**
42 			 * Linearly distort an image using the given Affine Matrix of 6 pre-calculated
43 			 * coefficients forming a set of Affine Equations to map the source
44 			 * image to the destination image.
45 			 * 
46 			 * Sx,Rx,Ry,Sy,Tx,Ty
47 			 */
48 			AffineProjectionDistortion,
49 
50 			/**
51 			 * Distort image by first scaling and rotating about a given
52 			 * 'center', before translating that 'center' to the new location,
53 			 * in that order. It is an alternative method of specifying a
54 			 * 'Affine' type of distortion, but without shearing effects. It
55 			 * also provides a good way of rotating and displacing a smaller
56 			 * image for tiling onto a larger background (IE 2-dimensional
57 			 * animations).
58 			 * 
59 			 * The number of arguments determine the specific meaning of each
60 			 * argument for the scales, rotation, and translation operations. 
61 			 * $(TABLE
62 			 *     $(HEADERS #, arguments meaning )
63 			 *     $(ROW 1:, $(COMMA Angle_of_Rotation ))
64 			 *     $(ROW 2:, $(COMMA Scale Angle ))
65 			 *     $(ROW 3:, $(COMMA X,Y Angle ))
66 			 *     $(ROW 4:, $(COMMA X,Y Scale Angle ))
67 			 *     $(ROW 5:, $(COMMA X,Y ScaleX,ScaleY Angle ))
68 			 *     $(ROW 6:, $(COMMA X,Y Scale Angle NewX,NewY ))
69 			 *     $(ROW 7:, $(COMMA X,Y ScaleX,ScaleY Angle NewX,NewY ))
70 			 * )
71 			 * 
72 			 * This is actually an alternative way of specifying a 2 dimensional
73 			 * linear 'Affine' or 'AffineProjection' distortion.
74 			 */
75 			ScaleRotateTranslateDistortion,
76 			
77 			/**
78 			 * Perspective distort the images, using a list of 4 or more sets of
79 			 * control points (as defined below). More that 4 sets (16 numbers) of
80 			 * control points provide least squares fitting for more accurate
81 			 * distortions (for the purposes of image registration and panarama
82 			 * effects). Less than 4 sets will fall back to a 'Affine' linear distortion.
83 			 * 
84 			 * Perspective Distorted images ensures that straight lines remain straight,
85 			 * but the scale of the distorted image will vary. The horizon is
86 			 * anti-aliased, and the 'sky' color may be set using the -mattecolor setting.
87 			 */
88 			PerspectiveDistortion,
89 			
90 			/**
91 			 * Do a Perspective distortion biased on a set of 8 pre-calculated coefficients.
92 			 * If the last two perspective scaling coefficients are zero, the remaining
93 			 * 6 represents a transposed 'Affine Matrix'.
94 			 */
95 			PerspectiveProjectionDistortion,
96 			
97 			/**
98 			 * Bilinear Distortion, given a minimum of 4 sets of coordinate pairs,
99 			 * or 16 values (see below). Not that lines may not appear straight
100 			 * after distortion, though the distance between coordinates will
101 			 * remain consistent.
102 			 * 
103 			 * The BilinearForward is used to map rectangles to any quadrilateral,
104 			 * while the BilinearReverse form maps any quadrilateral to a rectangle,
105 			 * while preserving the straigth line edges in each case.
106 			 * 
107 			 * Note that BilinearForward can generate invalid pixels which will be
108 			 * colored using the -mattecolor color setting. Also if the quadraterial
109 			 * becomes 'flipped' the image may dissappear.
110 			 * 
111 			 * There are future plans to produce a true Bilinear distortion that will
112 			 * attempt to map any quadrilateral to any other quadrilateral,
113 			 * while preserving edges (and edge distance ratios).
114 			 */
115 			BilinearForwardDistortion,
116 			
117 			/**
118 			 * ditto
119 			 */
120 			BilinearDistortion = BilinearForwardDistortion,
121 			
122 			/**
123 			 * ditto
124 			 */
125 			BilinearReverseDistortion,
126 			
127 			/**
128 			 * 
129 			 */
130 			PolynomialDistortion,
131 			
132 			/**
133 			 * Arc the image (variation of polar mapping) over the angle given around a circle.
134 			 * $(TABLE
135 			 *     $(HEADERS Argument,  Meaning)
136 			 *     $(ROW arc_angle,     The angle over which to arc the image side-to-side)
137 			 *     $(ROW rotate_angle,  Angle to rotate resulting image from vertical center)
138 			 *     $(ROW top_radius,    Set top edge of source image at this radius)
139 			 *     $(ROW bottom_radius, Set bottom edge to this radius (radial scaling))
140 			 * )
141 			 * 
142 			 * The resulting image is always resized to best fit the resulting image, while
143 			 * attempting to preserve scale and aspect ratio of the original image as much
144 			 * as possible with the arguments given by the user. All four arguments will be
145 			 * needed to change the overall aspect ratio of an 'Arc'ed image. 
146 			 * 
147 			 * This a variation of a polar distortion designed to try to preserve the aspect
148 			 * ratio of the image rather than direct Cartesian to Polar conversion.
149 			 */
150 			ArcDistortion,
151 			
152 			/**
153 			 * Like ArcDistortion but do a complete Cartesian to Polar mapping of the image.
154 			 * that is the height of the input image is mapped to the radius limits, while
155 			 * the width is wrapped around between the angle limits.
156 			 * 
157 			 * Arguments : Rmax,Rmin CenterX,CenterY, start,end_angle
158 			 * 
159 			 * All arguments are optional. With Rmin defaulting to zero, the center to the
160 			 * center of the image, and the angles going from -180 (top) to +180 (top). If
161 			 * Rmax is given the special value of '0', the the distance from the center to
162 			 * the nearest edge is used for the radius of the output image, which will ensure
163 			 * the whole image is visible (though scaled smaller). However a special value of
164 			 * '-1' will use the distance from the center to the furthest corner, This may
165 			 * 'clip' the corners from the input rectangular image, but will generate the
166 			 * exact reverse of a 'DePolar' with the same arguments.
167 			 */
168 			PolarDistortion,
169 			
170 			/**
171 			 * Uses the same arguments and meanings as a Polar distortion but generates the 
172 			 * reverse Polar to Cartesian distortion. 
173 			 * 
174 			 * The special Rmax setting of '0' may however clip the corners of the input image.
175 			 * However using the special Rmax setting of '-1' (maximum center to corner distance)
176 			 * will ensure the whole distorted image is preserved in the generated result, so that
177 			 * the same argument to 'Polar' will reverse the distortion re-producing the original.
178 			 * Note that as this distortion requires the area resampling of a circular arc, which
179 			 * can not be handled by the builtin EWA resampling function. As such the normal EWA
180 			 * filters are turned off. It is recommended some form of 'super-sampling' image
181 			 * processing technique be used to produce a high quality result.
182 			 */
183 			DePolarDistortion,
184 			
185 			/** */
186 			Cylinder2PlaneDistortion,
187 			
188 			/** */
189 			Plane2CylinderDistortion,
190 			
191 			/**
192 			 * Given the four coefficients (A,B,C,D) as defined by Helmut Dersch, perform a barrell or
193 			 * pin-cushion distortion appropriate to correct radial lens distortions. That is in
194 			 * photographs, make straight lines straight again.
195 			 * 
196 			 * Arguments : A B C [D [X,Y]] $(BR)
197 			 * or Ax Bx Cx Dx  Ay By Cy Dy [X,Y] $(BR)
198 			 * So that it forms the function $(BR)
199 			 * Rsrc = r * ( A*r³ + B*r² + C*r + D )
200 			 * 
201 			 * Where X,Y is the optional center of the distortion (defaulting to the center of the image).
202 			 * The second form is typically used to distort images, rather than correct lens distortions.
203 			 */
204 			BarrelDistortion,
205 			
206 			/**
207 			 * This is very simular to BarrelDistortion with the same set of arguments, and argument handling.
208 			 * However it uses the inverse of the radial polynomial, so that it forms the function 
209 			 * 
210 			 * Rsrc = r / ( A*r³ + B*r² + C*r + D )
211 			 * 
212 			 * Note that this is not the reverse of the Barrel distortion,
213 			 * just a different barrel-like radial distortion method.
214 			 */
215 			BarrelInverseDistortion,
216 			
217 			/**
218 			 * Distort the given list control points (any number) using an Inverse Squared Distance
219 			 * Interpolation Method (Shepards Method). The control points in effect do 'localized'
220 			 * displacement of the image around the given control point (preserving the look and the
221 			 * rotation of the area near the control points. For best results extra control points
222 			 * should be added to 'lock' the positions of the corners, edges and other unchanging
223 			 * parts of the image, to prevent their movement.
224 			 * 
225 			 * The distortion has been likened to 'taffy pulling' using nails, or pins' stuck in a
226 			 * block of 'jelly' which is then moved to the new position, distorting te surface of the jelly. 
227 			 */
228 			ShepardsDistortion,
229 			
230 			/** */
231 			ResizeDistortion,
232 
233 			/* Not a real distortion, ImageMagick uses this to get the amount of Distortions supported */
234 			SentinelDistortion
235 		}
236 	}
237 	else
238 	{
239 		mixin(
240 		{
241 			string methods = "enum DistortImageMethod
242 			{
243 				UndefinedDistortion,
244 				AffineDistortion,
245 				AffineProjectionDistortion,
246 				ScaleRotateTranslateDistortion,
247 				PerspectiveDistortion,
248 				PerspectiveProjectionDistortion,
249 				BilinearForwardDistortion,
250 				BilinearDistortion = BilinearForwardDistortion,
251 				BilinearReverseDistortion,
252 				PolynomialDistortion,
253 				ArcDistortion,
254 				PolarDistortion,
255 				DePolarDistortion,";
256 
257 				static if ( MagickLibVersion >= 0x671 )
258 				{
259 					methods ~= "Cylinder2PlaneDistortion,
260 						        Plane2CylinderDistortion,";
261 				}
262 
263 				methods ~= "
264 				BarrelDistortion,
265 				BarrelInverseDistortion,
266 				ShepardsDistortion,";
267 
268 				static if ( MagickLibVersion >= 0x670 )
269 				{
270 					methods ~= "ResizeDistortion,";
271 				}
272 
273 				methods ~= "
274 				SentinelDistortion
275 			}";
276 
277 			return methods;
278 		}());
279 	}
280 
281 	/**
282 	 * Determines how to fill intervening colors.
283 	 */
284 	enum SparseColorMethod
285 	{
286 		/** */
287 		UndefinedColorInterpolate =   cast(int)DistortImageMethod.UndefinedDistortion,
288 
289 		/**
290 		 * three point triangle of color given 3 points. Giving only 2 points
291 		 * will form a linear gradient between those points. The gradient
292 		 * generated extends beyond the triangle created by those 3 points.
293 		 */
294 		BarycentricColorInterpolate = cast(int)DistortImageMethod.AffineDistortion,
295 
296 		/**
297 		 * Like barycentric but for 4 points. Less than 4 points fall back
298 		 * to barycentric.
299 		 */
300 		BilinearColorInterpolate =    cast(int)DistortImageMethod.BilinearReverseDistortion,
301 
302 		/** */
303 		PolynomialColorInterpolate =  cast(int)DistortImageMethod.PolynomialDistortion,
304 
305 		/**
306 		 * Colors points biased on the ratio of inverse distance squared.
307 		 * Generating spots of color in a sea of the average of colors.
308 		 */
309 		ShepardsColorInterpolate =    cast(int)DistortImageMethod.ShepardsDistortion,
310 
311 		/**
312 		 * Simply map each pixel to the to nearest color point given.
313 		 * The result are polygonal cells of solid color.
314 		 */
315 		VoronoiColorInterpolate =     cast(int)DistortImageMethod.SentinelDistortion,
316 
317 		/**
318 		 * Colors points biased on the ratio of inverse distance.
319 		 * This generates sharper points of color rather than rounded spots
320 		 * of ShepardsColorInterpolate Generating spots of color in a sea
321 		 * of the average of colors.
322 		 */
323 		InverseColorInterpolate
324 	}
325 
326 	Image* AffineTransformImage(const(Image)*, const(AffineMatrix)*, ExceptionInfo*);
327 	Image* DistortImage(const(Image)*, const DistortImageMethod, const size_t, const(double)*, MagickBooleanType, ExceptionInfo* exception);
328 
329 	static if ( MagickLibVersion >= 0x670 )
330 	{
331 		Image* DistortResizeImage(const(Image)*, const size_t, const size_t, ExceptionInfo*);
332 	}
333 
334 	Image* RotateImage(const(Image)*, const double, ExceptionInfo*);
335 	Image* SparseColorImage(const(Image)*, const ChannelType, const SparseColorMethod, const size_t, const(double)*, ExceptionInfo*);
336 }