31 votes

étirement d'image d'iPhone (skew)

Comment puis-je m'incliner une image? Par exemple, chaque coin a une CGPoint avec coords - p1, p2, p3, p4. Ensuite, j'ai besoin de régler p4.x+=50, p4.y+=30. Donc, ce coin (p4) doit être étendu à un point de vue 2D et l'image ne doit pas être déformé.

alt text

J'ai essayé d'utiliser CATransform3D, mais il semble que cela ne peut être fait de telle façon, puisque c'est seulement un changement du point de vue (rotation, apporter plus près ou plus loin un côté). Peut-être CGAffineTransform peut-elle être utile?

Si vous connaissez la réponse, s'il vous plaît écrire un exemple de code.

Merci d'avance

81voto

KennyTM Points 232647

Pas possible avec CGAffineTransform. Une transformation affine peut toujours être décomposé en translations, rotations, de cisaillement et de mise à l'échelle. Ils ont tous la carte des parallélogrammes en parallélogrammes, qui votre transformation n'a pas.

Pour votre transformation, il peut être fait en deux étapes. De convertir la place dans un trapèze.

p1-----p2       p1-----p2
 |     |   -->   |       \
p3-----p4       p3--------p4'

Un autre pour la direction verticale. Un naïf règle de transformation est

                   y - c
x' = (x - p1.x) * -------- + p1.x
                  p1.y - c
y' = y

où c est l'abscisse du point d'intersection des lignes reliant p1 et p3 et p2 et p4.

Maintenant, remarquez le x*y facteur dans la transformation. Ceci indique qu'une telle transformation n'est pas linéaire. Par conséquent, CATransform3D ne peut effectuer qu'une transformation 2D soit.

Cependant, le vecteur

[x, y, z, w=1]

seront convertis à la réalité de vecteur 3D

(x/w, y/w, z/w)

avant la projection, si CA suit d'habitude 3D calculer les règles graphiques, de sorte que vous pouvez "tricher" en utilisant la transformation

[ P . . Q ] [ x ]   [ x' ]
[ . R . S ] [ y ] = [ y' ]
[ . . 1 . ] [ z ]   [ z' ]
[ . T . U ] [ 1 ]   [ w' ]

avec appropriée, P, Q, R, S, T, U, qui mappe les 4 points de la lieux. (6 unique coordonne et 6 variables devraient avoir exactement 1 solution de la plupart des cas.)

Lorsque vous avez trouvé ces 6 constantes, vous pouvez créer un CATransform3D. Avis de la définition de la structure est

struct CATransform3D
   {
   CGFloat m11, m12, m13, m14;
   CGFloat m21, m22, m23, m24;
   CGFloat m31, m32, m33, m34;
   CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;

Vous pouvez directement modifier les éléments de la matrice, au lieu de compter sur la CATransform3DMake fonctions. (Vous devrez peut-être effectuer une transposition grâce à la convention de l'utilisation de la ligne ou de la colonne des vecteurs.)


Pour obtenir la transformation pour convertir un rectangle ((X, Y), (W, H)) pour tout quadrilatère ((x1a) y1a), (x2a, y2a); (x3a, y3a), (x4a, y4a)), l'utilisation de cette fonction (vous pouvez avoir besoin d'une transposition):

function compute_transform_matrix(X, Y, W, H, x1a, y1a, x2a, y2a, x3a, y3a, x4a, y4a) {
    var y21 = y2a - y1a, 
        y32 = y3a - y2a,
        y43 = y4a - y3a,
        y14 = y1a - y4a,
        y31 = y3a - y1a,
        y42 = y4a - y2a;

    var a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42);
    var b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);
    var c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);

    var d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a);
    var e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42);
    var f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a)));

    var g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43);
    var h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42);
    var i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a));

    return [[a,b,0,c],[d,e,0,f],[0,0,1,0],[g,h,0,i]];
}

7voto

hfossli Points 6815

Transformation 3D sur UIImage / CGImageRef

Vous devriez être en mesure de calculer la cartographie de chaque pixel par vous-même.. Pas parfait, mais il fait l'affaire...

Elle est disponible sur ce référentiel http://github.com/hfossli/AGGeometryKit/

Les fichiers intéressants est

https://github.com/hfossli/AGGeometryKit/blob/master/Source/AGTransformPixelMapper.m

https://github.com/hfossli/AGGeometryKit/blob/master/Source/CGImageRef%2BCATransform3D.m

https://github.com/hfossli/AGGeometryKit/blob/master/Source/UIImage%2BCATransform3D.m


Transformation 3D sur UIView / UIImageView

http://stackoverflow.com/a/12820877/202451

Ensuite, vous aurez le plein contrôle sur chaque point dans le quadrilatère. :)

3voto

jothikenpachi Points 425
<pre><code></code><p><code></code><code></code>pour obtenir une telle forme.</p></pre>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X