### Article Purpose

This article is focussed on illustrating the steps required in performing an . All of the concepts explored have been implemented by means of raw pixel data processing, no conventional drawing methods, such as GDI, are required.

Rabbit: Shear X 0.4, Y 0.4

### Sample Source Code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

### Using the Sample Application

article features a based sample application which is included as part of the accompanying sample source code. The concepts explored in this article can be illustrated in a practical implementation using the sample application.

The sample application enables a user to load source/input from the local system when clicking the Load Image button. In addition users are also able to save output result to the local file system by clicking the Save Image button.

Image can be applied to either X or Y, or both X and Y pixel coordinates. When using the sample application the user has option of adjusting Shear factors, as indicated on the user interface by the numeric up/down controls labelled Shear X and Shear Y.

The following image is a screenshot of the Image Transform Shear Sample Application in action:

Rabbit: Shear X -0.5, Y -0.25

### Image Shear Transformation

A good definition of the term can be found on the Wikipedia :

In , a shear mapping is a that displaces each point in fixed direction, by an amount proportional to its signed distance from a line that is to that direction.[1] This type of mapping is also called shear transformation, transvection, or just shearing

A can be applied as a horizontal shear, a vertical shear or as both. The algorithms implemented when performing a can be expressed as follows:

Horizontal Shear Algorithm

Vertical Shear Algorithm

The algorithm description:

• Shear(x) : The result of a horizontal – The calculated X-Coordinate representing a .
• Shear(y) : The result of a vertical – The calculated Y-Coordinate representing a .
• σ : The lower case version of the Greek alphabet letter Sigma – Represents the Shear Factor.
• x : The X-Coordinate originating from the source/input – The horizontal coordinate value intended to be sheared.
• y : The Y-Coordinate originating from the source/input – The vertical coordinate value intended to be sheared.
• H : Source height in pixels.
• W : Source width in pixels.

Note: When performing a implementing both the horizontal and vertical planes each coordinate plane can be calculated using a different shearing factor.

The algorithms have been adapted in order to implement a middle pixel offset by means of subtracting the product of the related plane boundary and the specified Shearing Factor, which will then be divided by a factor of two.

Rabbit: Shear X 1.0, Y 0.1

### Implementing a Shear Transformation

The sample source code performs through the implementation of the ShearXY and ShearImage.

The ShearXY targets the structure. The algorithms discussed in the previous sections have been implemented in this function from a C# perspective. The definition as illustrated by the following code snippet:

```public static Point ShearXY(this Point source, double shearX,
double shearY,
int offsetX,
int offsetY)
{
Point result = new Point();

result.X = (int)(Math.Round(source.X + shearX * source.Y));
result.X -= offsetX;

result.Y = (int)(Math.Round(source.Y + shearY * source.X));
result.Y -= offsetY;

return result;
} ```

Rabbit: Shear X 0.0, Y 0.5

The ShearImage targets the class. This method expects as parameter values a horizontal and a vertical shearing factor. Providing a shearing factor of zero results in no shearing being implemented in the corresponding direction. The definition as follows:

```public static Bitmap ShearImage(this Bitmap sourceBitmap,
double shearX,
double shearY)
{
BitmapData sourceData =
sourceBitmap.LockBits(new Rectangle(0, 0,
sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);

byte[] pixelBuffer = new byte[sourceData.Stride *
sourceData.Height];

byte[] resultBuffer = new byte[sourceData.Stride *
sourceData.Height];

Marshal.Copy(sourceData.Scan0, pixelBuffer, 0,
pixelBuffer.Length);

sourceBitmap.UnlockBits(sourceData);

int xOffset = (int )Math.Round(sourceBitmap.Width *
shearX / 2.0);

int yOffset = (int )Math.Round(sourceBitmap.Height *
shearY / 2.0);

int sourceXY = 0;
int resultXY = 0;

Point sourcePoint = new Point();
Point resultPoint = new Point();

Rectangle imageBounds = new Rectangle(0, 0,
sourceBitmap.Width,
sourceBitmap.Height);

for (int row = 0; row < sourceBitmap.Height; row++)
{
for (int col = 0; col < sourceBitmap.Width; col++)
{
sourceXY = row * sourceData.Stride + col * 4;

sourcePoint.X = col;
sourcePoint.Y = row;

if (sourceXY >= 0 &&
sourceXY + 3 < pixelBuffer.Length)
{
resultPoint = sourcePoint.ShearXY(shearX,
shearY, xOffset, yOffset);

resultXY = resultPoint.Y * sourceData.Stride +
resultPoint.X * 4;

if (imageBounds.Contains(resultPoint) &&
resultXY >= 0)
{
if (resultXY + 6 <= resultBuffer.Length)
{
resultBuffer[resultXY + 4] =
pixelBuffer[sourceXY];

resultBuffer[resultXY + 5] =
pixelBuffer[sourceXY + 1];

resultBuffer[resultXY + 6] =
pixelBuffer[sourceXY + 2];

resultBuffer[resultXY + 7] = 255;
}

if (resultXY - 3 >= 0)
{
resultBuffer[resultXY - 4] =
pixelBuffer[sourceXY];

resultBuffer[resultXY - 3] =
pixelBuffer[sourceXY + 1];

resultBuffer[resultXY - 2] =
pixelBuffer[sourceXY + 2];

resultBuffer[resultXY - 1] = 255;
}

if (resultXY + 3 < resultBuffer.Length)
{
resultBuffer[resultXY] =
pixelBuffer[sourceXY];

resultBuffer[resultXY + 1] =
pixelBuffer[sourceXY + 1];

resultBuffer[resultXY + 2] =
pixelBuffer[sourceXY + 2];

resultBuffer[resultXY + 3] = 255;
}
}
}
}
}

Bitmap resultBitmap = new Bitmap(sourceBitmap.Width,
sourceBitmap.Height);

BitmapData resultData =
resultBitmap.LockBits(new Rectangle(0, 0,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb);

Marshal.Copy(resultBuffer, 0, resultData.Scan0,
resultBuffer.Length);

resultBitmap.UnlockBits(resultData);

return resultBitmap;
} ```

Rabbit: Shear X 0.5, Y 0.0

### Sample Images

This article features a number of sample images. All featured images have been licensed allowing for reproduction.

The sample images featuring the image of a Desert Cottontail Rabbit is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from Wikipedia. The original author is attributed as Larry D. Moore.

The sample images featuring the image of a Rabbit in Snow is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from Wikipedia. The original author is attributed as George Tuli.

The sample images featuring the image of an Eastern Cottontail Rabbit has been released into the public domain by its author. The original image can be downloaded from .

The sample images featuring the image of a Mountain Cottontail Rabbit is in the public domain in the United States because it is a work prepared by an officer or employee of the United States Government as part of that person’s official duties under the terms of Title 17, Chapter 1, Section 105 of the US Code. The original image can be downloaded from .

Rabbit: Shear X 1.0, Y 0.0

Rabbit: Shear X 0.5, Y 0.1

Rabbit: Shear X -0.5, Y -0.25

Rabbit: Shear X -0.5, Y 0.0

Rabbit: Shear X 0.25, Y 0.0

Rabbit: Shear X 0.50, Y 0.0

Rabbit: Shear X 0.0, Y 0.5

Rabbit: Shear X 0.0, Y 0.25

Rabbit: Shear X 0.0, Y 1.0

### Related Articles and Feedback

Feedback and questions are always encouraged. If you know of an alternative implementation or have ideas on a more efficient implementation please share in the comments section.

I’ve published a number of articles related to imaging and images of which you can find URL links here:

#### 29 Responses to “C# How to: Image Transform Shear”

1. 1 C# How to: Compass Edge Detection | Software by Default Trackback on June 22, 2013 at 9:35 PM
2. 2 C# How to: Oil Painting and Cartoon Filter | Software by Default Trackback on June 30, 2013 at 10:48 AM
3. 3 C# How to: Stained Glass Image Filter | Software by Default Trackback on June 30, 2013 at 10:50 AM
4. 4 C# How to: Image Transform Rotate | Software by Default Trackback on June 30, 2013 at 1:24 PM
5. 5 C# How to: Image Blur | Software by Default Trackback on June 30, 2013 at 1:35 PM
6. 6 C# How to: Calculating Gaussian Kernels | Software by Default Trackback on June 30, 2013 at 1:40 PM
7. 7 C# How to: Image Cartoon Effect | Software by Default Trackback on June 30, 2013 at 1:45 PM
8. 8 C# How to: Boolean Edge Detection | Software by Default Trackback on June 30, 2013 at 1:56 PM
9. 9 C# How to: Morphological Edge Detection | Software by Default Trackback on June 30, 2013 at 2:02 PM
10. 10 C# How to: Image Erosion and Dilation | Software by Default Trackback on June 30, 2013 at 2:11 PM
11. 11 C# How to: Image Colour Average | Software by Default Trackback on June 30, 2013 at 2:20 PM
12. 12 C# How to: Image Unsharp Mask | Software by Default Trackback on June 30, 2013 at 2:28 PM
13. 13 C# How to: Image Median Filter | Software by Default Trackback on June 30, 2013 at 3:16 PM
14. 14 C# How to: Difference Of Gaussians | Software by Default Trackback on June 30, 2013 at 3:28 PM
15. 15 C# How to: Image Edge Detection | Software by Default Trackback on June 30, 2013 at 3:33 PM
16. 16 C# How to: Image Convolution | Software by Default Trackback on June 30, 2013 at 3:55 PM
17. 17 C# How to: Generate a Web Service from WSDL | Software by Default Trackback on June 30, 2013 at 4:08 PM
18. 18 C# How to: Decoding/Converting Base64 strings to Bitmap images | Software by Default Trackback on June 30, 2013 at 4:14 PM
19. 19 C# How to: Bitmap Colour Substitution implementing thresholds | Software by Default Trackback on July 6, 2013 at 4:33 PM
20. 20 C# How to: Swapping Bitmap ARGB Colour Channels | Software by Default Trackback on July 6, 2013 at 5:02 PM
21. 21 C# How to: Image filtering by directly manipulating Pixel ARGB values | Software by Default Trackback on July 8, 2013 at 2:58 AM
22. 22 C# How to: Image ASCII Art | Software by Default Trackback on July 14, 2013 at 7:23 AM
23. 23 C# How to: Weighted Difference of Gaussians | Software by Default Trackback on July 14, 2013 at 8:12 PM
24. 24 C# How to: Image Boundary Extraction | Software by Default Trackback on July 21, 2013 at 10:24 AM
25. 25 C# How to: Image Abstract Colours Filter | Software by Default Trackback on July 28, 2013 at 7:41 PM
26. 26 C# How to: Fuzzy Blur Filter | Software by Default Trackback on August 9, 2013 at 6:40 AM
27. 27 C# How to: Image Distortion Blur | Software by Default Trackback on August 9, 2013 at 10:13 PM
28. 28 C# How to: Standard Deviation Edge Detection | Software by Default Trackback on August 8, 2015 at 8:10 AM
29. 29 C# How to: Min/Max Edge Detection | Software by Default Trackback on August 9, 2015 at 11:30 AM

• 809,209 hits

## Follow SoftwareByDefault via Email

Enter your email address to follow and receive notifications of new posts by email.

Join 226 other followers