/// <summary> /// (1) For very small rotations, just return a clone. /// (2) Generate larger image to embed pixs if necessary, and /// place the center of the input image in the center. /// (3) Rotation brings either white or black pixels in /// from outside the image. For colormapped images where /// there is no white or black, a new color is added if /// possible for these pixels; otherwise, either the /// lightest or darkest color is used. In most cases, /// the colormap will be removed prior to rotation. /// (4) The dest is to be expanded so that no image pixels /// are lost after rotation. Input of the original width /// and height allows the expansion to stop at the maximum /// required size, which is a square with side equal to /// sqrt(w*w + h*h). /// (5) For an arbitrary angle, the expansion can be found by /// considering the UL and UR corners. As the image is /// rotated, these move in an arc centered at the center of /// the image. Normalize to a unit circle by dividing by half /// the image diagonal. After a rotation of T radians, the UL /// and UR corners are at points T radians along the unit /// circle. Compute the x and y coordinates of both these /// points and take the max of absolute values; these represent /// the half width and half height of the containing rectangle. /// The arithmetic is done using formulas for sin(a+b) and cos(a+b), /// where b = T. For the UR corner, sin(a) = h/d and cos(a) = w/d. /// For the UL corner, replace a by (pi - a), and you have /// sin(pi - a) = h/d, cos(pi - a) = -w/d. The equations /// given below follow directly. /// </summary> /// <param name="pixs">1, 2, 4, 8, 32 bpp rgb</param> /// <param name="angle">radians; clockwise is positive</param> /// <param name="incolor">L_BRING_IN_WHITE, L_BRING_IN_BLACK</param> /// <param name="width">original width; use 0 to avoid embedding</param> /// <param name="height">original height; use 0 to avoid embedding</param> /// <returns>pixd, or NULL on error</returns> public static Pix pixEmbedForRotation(this Pix pixs, float angle, BackgroundFlags incolor, int width, int height) { if (null == pixs) { throw new ArgumentNullException("pixs cannot be null."); } var pointer = Native.DllImports.pixEmbedForRotation((HandleRef)pixs, angle, incolor, width, height); if (IntPtr.Zero == pointer) { return(null); } else { return(new Pix(pointer)); } }
/// <summary> /// (1) Brings in either black or white pixels from the boundary. /// (2) Retains colormap, which you can do for a sampled transform.. /// (3) For 8 or 32 bpp, much better quality is obtained by the /// somewhat slower pixAffine(). See that function /// for relative timings between sampled and interpolated. /// </summary> /// <param name="pixs">all depths</param> /// <param name="vc">vector of 6 coefficients for affine transformation</param> /// <param name="incolor">L_BRING_IN_WHITE, L_BRING_IN_BLACK</param> /// <returns>pixd, or NULL on error</returns> public static Pix pixAffineSampled(this Pix pixs, IntPtr vc, BackgroundFlags incolor) { if (null == pixs || null == vc) { throw new ArgumentNullException("pixs, vc cannot be null."); } var pointer = Native.DllImports.pixAffineSampled((HandleRef)pixs, vc, incolor); if (IntPtr.Zero == pointer) { return(null); } else { return(new Pix(pointer)); } }
// Affine (3 pt) image transformation using interpolation (or area mapping) for anti-aliasing images that are 2, 4, or 8 bpp gray, or colormapped, or 32 bpp RGB /// <summary> /// (1) Brings in either black or white pixels from the boundary /// (2) Removes any existing colormap, if necessary, before transforming /// </summary> /// <param name="pixs">all depths; colormap ok</param> /// <param name="ptad">3 pts of final coordinate space</param> /// <param name="ptas">3 pts of initial coordinate space</param> /// <param name="incolor">L_BRING_IN_WHITE, L_BRING_IN_BLACK</param> /// <returns>pixd, or NULL on error</returns> public static Pix pixAffinePta(this Pix pixs, Pta ptad, Pta ptas, BackgroundFlags incolor) { if (null == pixs || null == ptad || null == ptas) { throw new ArgumentNullException("pixs, ptad, ptas cannot be null."); } var pointer = Native.DllImports.pixAffinePta((HandleRef)pixs, (HandleRef)ptad, (HandleRef)ptas, incolor); if (IntPtr.Zero == pointer) { return(null); } else { return(new Pix(pointer)); } }
// Nice(slow) rotation of 1 bpp image /// <summary> /// (1) For very small rotations, just return a clone. /// (2) This does a computationally expensive rotation of 1 bpp images. /// The fastest rotators (using shears or subsampling) leave /// visible horizontal and vertical shear lines across which /// the image shear changes by one pixel. To ameliorate the /// visual effect one can introduce random dithering. One /// way to do this in a not-too-random fashion is given here. /// We convert to 8 bpp, do a very small blur, rotate using /// linear interpolation (same as area mapping), do a /// small amount of sharpening to compensate for the initial /// blur, and threshold back to binary. The shear lines /// are magically removed. /// (3) This operation is about 5x slower than rotation by sampling. /// </summary> /// <param name="pixs">1 bpp</param> /// <param name="angle">radians; clockwise is positive; about the center</param> /// <param name="incolor">L_BRING_IN_WHITE, L_BRING_IN_BLACK</param> /// <returns>pixd, or NULL on error</returns> public static Pix pixRotateBinaryNice(this Pix pixs, float angle, BackgroundFlags incolor) { if (null == pixs) { throw new ArgumentNullException("pixs cannot be null."); } if (1 != pixs.Depth) { throw new ArgumentException("pixs must be 1 bpp."); } var pointer = Native.DllImports.pixRotateBinaryNice((HandleRef)pixs, angle, incolor); if (IntPtr.Zero == pointer) { return(null); } else { return(new Pix(pointer)); } }
// General rotation by sampling /// <summary> /// (1) For very small rotations, just return a clone. /// (2) Rotation brings either white or black pixels in /// from outside the image. /// (3) Colormaps are retained. /// </summary> /// <param name="pixs">1, 2, 4, 8, 16, 32 bpp rgb; can be cmapped</param> /// <param name="xcen">x value of center of rotation</param> /// <param name="ycen">y value of center of rotation</param> /// <param name="angle">radians; clockwise is positive</param> /// <param name="incolor">L_BRING_IN_WHITE, L_BRING_IN_BLACK</param> /// <returns>pixd, or NULL on error</returns> public static Pix pixRotateBySampling(this Pix pixs, int xcen, int ycen, float angle, BackgroundFlags incolor) { if (null == pixs) { throw new ArgumentNullException("pixs cannot be null."); } var pointer = Native.DllImports.pixRotateBySampling((HandleRef)pixs, xcen, ycen, angle, incolor); if (IntPtr.Zero == pointer) { return(null); } else { return(new Pix(pointer)); } }