Question

Je dois transformer des images bitmap en déplaçant leurs 4 coins d'angle d'un emplacement à un autre.

Tout code pouvant fonctionner sous Windows, C # / VB.NET de préférence, même pour vous aider à utiliser des programmes scriptés comme Paint.NET ou Photoshop seraient acceptés. L’API Java Advanced Imaging semble prometteuse.

J'en ai besoin pour un système de manipulation de capture d'écran, qui vous permet d'obtenir de tels effets:

 alt text
(source: wholetomato.com )

Était-ce utile?

La solution

Découvrez les Perspective déformant exemples tirés de ImageMagick . Il est disponible pour la plupart des plateformes grand public.

Autres conseils

Le mot clé ici est homographie . Manolis Lourakis a écrit une implémentation d'homographie GPL en C, disponible ici . ; cependant, cela ne pourra pas être porté très facilement car il repose sur des bibliothèques externes telles que LAPACK .

Avertissement: je travaille chez Atalasoft

Si vous êtes prêt à devenir commercial, DotImage Photo peut le faire avec la QuadrilateralWarpCommand. Exemple de code C #

// Load an image.
AtalaImage image = new AtalaImage("test-image.jpg");

// Prepare the warp positions.
Point bottomLeft = new Point(100, image.Height - 80);
Point topLeft = new Point(130, 45);
Point topRight = new Point(image.Width - 60, 140);
Point bottomRight = new Point(image.Width - 20, image.Height);

// Warp the image.
QuadrilateralWarpCommand cmd = new QuadrilateralWarpCommand(bottomLeft,
   topLeft, topRight, bottomRight, InterpolationMode.BiLinear, Color.White);
AtalaImage result = cmd.Apply(image).Image;

http://www.atalasoft.com/products/dotimage

Plus simple que de simuler une distorsion de perspective à l'aide de la manipulation d'image, vous pouvez utiliser OpenGL ou DirectX (XNA) pour réellement afficher la perspective.

Rendez un quad simple avec votre image en tant que texture. Configurez votre scène, rendez-la dans un tampon et vous avez votre image.

Mise à jour Il s'avère que XNA est une bibliothèque ridicule (conçue pour créer des jeux et rien d'autre, bâillez). DirectX géré nécessite une lobotomie cérébrale. OpenGL est facile à utiliser, mais manque de code de chargement d'image. Cela nous laisse avec WPF:

texte alt http://praeclarum.org/so/persp.png

L'image pourrait être améliorée en forçant WPF en mode anti-alias (pourquoi oh pourquoi Microsoft est-il aussi myope?), et en n'utilisant pas le verre Aero qui impose une bordure noire de 1 pixel sur toutes les captures d'écran (ou en supprimant cette bordure de 1 pixel).

(Désolé pour la longueur de ce code, mais WPF est une API bavarde.)

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];
    }
}

Et le XAML requis:

<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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top