C# Silverlight&;缩放位图图像,使其适合矩形而不进行裁剪
我需要旋转一个WriteableBitmap,并在它被裁剪之前将其放大或缩小 我当前的代码将旋转,但如果高度大于宽度,则会裁剪边 我想我需要扩大规模C# Silverlight&;缩放位图图像,使其适合矩形而不进行裁剪,c#,silverlight,windows-phone-7,rotation,windows-phone,C#,Silverlight,Windows Phone 7,Rotation,Windows Phone,我需要旋转一个WriteableBitmap,并在它被裁剪之前将其放大或缩小 我当前的代码将旋转,但如果高度大于宽度,则会裁剪边 我想我需要扩大规模 public WriteableBitmap Rotate(WriteableBitmap Source, double Angle) { RotateTransform rt = new RotateTransform(); rt.Angle = Angle;
public WriteableBitmap Rotate(WriteableBitmap Source, double Angle)
{
RotateTransform rt = new RotateTransform();
rt.Angle = Angle;
TransformGroup transform = new TransformGroup();
transform.Children.Add(rt);
Image tempImage2 = new Image();
WriteableBitmap wb;
rt.CenterX = Source.PixelWidth / 2;
rt.CenterY = Source.PixelHeight / 2;
tempImage2.Width = Source.PixelWidth;
tempImage2.Height = Source.PixelHeight;
wb = new WriteableBitmap((int)(Source.PixelWidth), Source.PixelHeight);
tempImage2.Source = Source;
tempImage2.UpdateLayout();
wb.Render(tempImage2, transform);
wb.Invalidate();
return wb;
}
如何缩小图像比例,使其不会被裁剪?或者还有其他方法吗?您需要根据角点相对于中心的旋转来计算缩放比例。 如果图像是正方形,则只需要一个角,但对于矩形,需要检查两个角,以查看垂直或水平边是否重叠。此检查是对超出矩形高度和宽度的线性比较 伪代码如下(最后是实际的C代码):
- 将旋转角度转换为弧度
- 计算从矩形中心到角的“半径”
- 将BR角点位置转换为极坐标
- 将BL角点位置转换为极坐标
- 将旋转应用于两个极坐标
- 将新位置转换回笛卡尔坐标(ABS值)
- 找到两个水平位置中最大的一个
- 找到两个垂直位置中最大的一个
- 计算水平尺寸的增量变化
- 计算垂直尺寸的增量变化
- 水平变化较大时返回宽度/2/x
- 如果垂直变化较大,返回高度为2/y
如何缩小图像比例,使其不会被裁剪?还是有别的办法?
double CalculateConstraintScale(double rotation, int pixelWidth, int pixelHeight)
/// <summary>
/// Calculate the scaling required to fit a rectangle into a rotation of that same rectangle
/// </summary>
/// <param name="rotation">Rotation in degrees</param>
/// <param name="pixelWidth">Width in pixels</param>
/// <param name="pixelHeight">Height in pixels</param>
/// <returns>A scaling value between 1 and 0</returns>
/// <remarks>Released to the public domain 2011 - David Johnston (HiTech Magic Ltd)</remarks>
private double CalculateConstraintScale(double rotation, int pixelWidth, int pixelHeight)
{
// Convert angle to radians for the math lib
double rotationRadians = rotation * PiDiv180;
// Centre is half the width and height
double width = pixelWidth / 2.0;
double height = pixelHeight / 2.0;
double radius = Math.Sqrt(width * width + height * height);
// Convert BR corner into polar coordinates
double angle = Math.Atan(height / width);
// Now create the matching BL corner in polar coordinates
double angle2 = Math.Atan(height / -width);
// Apply the rotation to the points
angle += rotationRadians;
angle2 += rotationRadians;
// Convert back to rectangular coordinate
double x = Math.Abs(radius * Math.Cos(angle));
double y = Math.Abs(radius * Math.Sin(angle));
double x2 = Math.Abs(radius * Math.Cos(angle2));
double y2 = Math.Abs(radius * Math.Sin(angle2));
// Find the largest extents in X & Y
x = Math.Max(x, x2);
y = Math.Max(y, y2);
// Find the largest change (pixel, not ratio)
double deltaX = x - width;
double deltaY = y - height;
// Return the ratio that will bring the largest change into the region
return (deltaX > deltaY) ? width / x : height / y;
}
private WriteableBitmap GenerateConstrainedBitmap(BitmapImage sourceImage, int pixelWidth, int pixelHeight, double rotation)
{
double scale = CalculateConstraintScale(rotation, pixelWidth, pixelHeight);
// Create a transform to render the image rotated and scaled
var transform = new TransformGroup();
var rt = new RotateTransform()
{
Angle = rotation,
CenterX = (pixelWidth / 2.0),
CenterY = (pixelHeight / 2.0)
};
transform.Children.Add(rt);
var st = new ScaleTransform()
{
ScaleX = scale,
ScaleY = scale,
CenterX = (pixelWidth / 2.0),
CenterY = (pixelHeight / 2.0)
};
transform.Children.Add(st);
// Resize to specified target size
var tempImage = new Image()
{
Stretch = Stretch.Fill,
Width = pixelWidth,
Height = pixelHeight,
Source = sourceImage,
};
tempImage.UpdateLayout();
// Render to a writeable bitmap
var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
writeableBitmap.Render(tempImage, transform);
writeableBitmap.Invalidate();
return writeableBitmap;
}