легче, чем имитируя перспективу искажать с помощью манипуляции с изображениями, вы можете использовать OpenGL или DirectX (XNA) в фактически выполняют отображение перспективы.
Извлечь простой квадратик с изображением в качестве текстурной карты. Настройте свою сцену, визуализируйте в буфер, и у вас есть изображение.
Обновление Получается, что XNA - это смешная библиотека (предназначенная для создания игр и ничего больше, зевая). Управляемый DirectX требует лоботомии мозга. OpenGL прост в использовании, но отсутствует код загрузки изображения. Это оставляет нас с WPF:
alt text http://praeclarum.org/so/persp.png
Изображение может быть улучшено путем принуждения WPF в режиме анти-псевдонима (почему о, почему Microsoft вы так близоруким?), И не используя Aero стекла, силы что 1 пиксельная черная рамка на всех снимках экрана (или путем удаления этой 1 пиксельной границы).
(Извините за длину этого кода, но WPF является болтливый API.)
public partial class Window1 : Window {
const float ANGLE = 30;
const float WIDTH = 8;
public Window1() {
InitializeComponent();
var group = new Model3DGroup();
group.Children.Add(Create3DImage(@"C:\Users\fak\Pictures\so2.png"));
group.Children.Add(new AmbientLight(Colors.White));
ModelVisual3D visual = new ModelVisual3D();
visual.Content = group;
viewport.Children.Add(visual);
}
private GeometryModel3D Create3DImage(string imgFilename) {
var image = LoadImage(imgFilename);
var mesh = new MeshGeometry3D();
var height = (WIDTH * image.PixelHeight)/image.PixelWidth;
var w2 = WIDTH/2.0;
var h2 = height/2.0;
mesh.Positions.Add(new Point3D(-w2, -h2, 0));
mesh.Positions.Add(new Point3D(w2, -h2, 0));
mesh.Positions.Add(new Point3D(w2, h2, 0));
mesh.Positions.Add(new Point3D(-w2, h2, 0));
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(3);
mesh.TextureCoordinates.Add(new Point(0, 1)); // 0, 0
mesh.TextureCoordinates.Add(new Point(1, 1));
mesh.TextureCoordinates.Add(new Point(1, 0));
mesh.TextureCoordinates.Add(new Point(0, 0));
var mat = new DiffuseMaterial(new ImageBrush(image));
mat.AmbientColor = Colors.White;
var geometry = new GeometryModel3D();
geometry.Geometry = mesh;
geometry.Material = mat;
geometry.BackMaterial = mat;
geometry.Transform = new RotateTransform3D(
new AxisAngleRotation3D(new Vector3D(0,1,0), ANGLE),
new Point3D(0, 0, 0));
return geometry;
}
public static BitmapSource LoadImage(string filename) {
return BitmapDecoder.Create(new Uri(filename, UriKind.RelativeOrAbsolute),
BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];
}
}
И требуется XAML:
<Window x:Class="Persp.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Perspective Window" Height="480" Width="640">
<Grid>
<Viewport3D x:Name="viewport">
<Viewport3D.Resources>
</Viewport3D.Resources>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="cam"
FarPlaneDistance="100"
LookDirection="0,0,-1"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="0,0,10"
FieldOfView="60" />
</Viewport3D.Camera>
</Viewport3D>
</Grid>
</Window>
Проблема в том, как вы преобразовываете 4 точки в 3D-поворот? –