locked
WriteableBitmap et rotation d'image RRS feed

  • Question

  • Bonjour tout le monde,

     

    J'ai une  image stockée dans un WriteableBitmap, cette image est en fait une photo. Sur cette image j'ai repéré deux pixels et donc stocké les coordonnées de ces points. Je fait pivoter mon image afin d'aligner mes deux points puis je modifie mes coordonnées stockées pour qu'elle corresponde au nouvelle après rotation.

    Le problème c'est que mon système de rotation soit fait sortir une partie de de l'image et donc ma distance (centre image, point stockée) n'est plus la même et donc je n'arrive pas à retrouver mon point soit je stretch l'image et dans ce cas j'ai le même problème mais au moins je suis sur que mes points sont toujours présents.

     

    Voila ma méthode de rotation :

     

    private WriteableBitmap GenerateConstrainedBitmap(BitmapImage sourceImage, int pixelWidth, int pixelHeight, double rotation)
        {
          double scale = CalculateConstraintScale(rotation, pixelWidth, pixelHeight);
    
          
          var transform = new TransformGroup();
          var rt = new RotateTransform()
          {
            Angle = rotation,
            CenterX = (pixelWidth / 2),
            CenterY = (pixelHeight / 2)
          };
          transform.Children.Add(rt);
          var st = new ScaleTransform()
          {
            ScaleX = scale,
            ScaleY = scale,
            CenterX = (pixelWidth / 2),
            CenterY = (pixelHeight / 2)
          };
          transform.Children.Add(st);
    
          var tempImage = new Image()
          {
            Stretch = Stretch.Fill,
            Width = pixelWidth,
            Height = pixelHeight,
            Source = sourceImage,
          };
    
          tempImage.UpdateLayout();
    
          var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
          writeableBitmap.Render(tempImage, transform);
          writeableBitmap.Invalidate();
          return writeableBitmap;
    
        }
    


    Je cherche donc un moyen de conserver la taille de mon segment. Je pense que ce qu'il me manque c'est un moyen de connaitre avant même la rotation de l'image les x, et y min et max de l'image une fois sa rotation réalisée.

     

    Je vous remercie par avance !

    mardi 23 août 2011 15:09

Réponses

  •    var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
    

     Tu crées une image ayant les memes dimensions que ta source, ce qui est incorrect, car ton image a été rotationné, il faut donc que tu recalcules  la nouvelle taille de ton image.

     

    aide : 

    http://mathocollege.free.fr/brevet/angles/angles.html


    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue
    • Marqué comme réponse Sebastien.F mercredi 24 août 2011 08:29
    mardi 23 août 2011 16:39
    Modérateur

Toutes les réponses

  •    var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
    

     Tu crées une image ayant les memes dimensions que ta source, ce qui est incorrect, car ton image a été rotationné, il faut donc que tu recalcules  la nouvelle taille de ton image.

     

    aide : 

    http://mathocollege.free.fr/brevet/angles/angles.html


    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue
    • Marqué comme réponse Sebastien.F mercredi 24 août 2011 08:29
    mardi 23 août 2011 16:39
    Modérateur
  • Oui en effet, je m'en suis rendu compte... Il faut tout simplement que je calcule la nouvelle position de mes coins d'images pour obtenir les nouveaux min_x, min_y, max_x et max_y ce qui me donnera les nouvelles hauteur et largeur de mon image. ;)

     

    Merci pour cette réponse !

    mercredi 24 août 2011 07:28
  • Je reviens vers vous car mon problème n'est pas entièrement résolu. En conservant pour mon image source sa taille d'origine et en augmentant la taille de l'image final à l'aide de la position des coins après rotation j'obtiens de très bon résultat seulement si l'angle est petit. Plus l'angle est grand et plus la place de l'image de base est petite dans l'image de sortie alors que techniquement les coins de l'image source devrait toujours toucher les bords de l'image final, ce qui n'est pas le cas actuellement.

     

    Je vais vous fournir tout le code concerné avec des explication pour que ce la soit plus claire.

    Petite information : je vérifié les résultats obtenues en les recalculant à la main.

     

    Ici je calcule mon sinus est cosinus pour pouvoir effectuer mes rotations (je dois vérifier que le résultat n'est pas négatif car pour une raison qui m'est obscure cela peut arriver...)

     

     

     

    double cos, sin;
    
    cos = Math.Cos(angleT1T2 * Math.PI / 180);
    sin = Math.Sin(angleT1T2 * Math.PI / 180);
    
    if (cos < 0) cos = -cos;
    if (sin < 0) sin = -sin;
    

     

     

     


    Ici j'applique la formule de changement de position d'un point par rapport à un repère (ici le centre de l'image) :

     

     

     

    new_x = (int)(save_x * cos - save_y * sin );
    new_y = (int)(save_x * sin + save_y * cos );

     

     


    Ici je réalise la même opération mais cette fois-ci avec les quatres coins de mon image :

     

     

     

    int hg_x, hg_y, hd_x, hd_y, bg_x, bg_y, bd_x, bd_y;
    
    hg_x = (int)( (-(_width/2)) * cos - (_height/2) * sin );
    hg_y = (int)((-(_width / 2)) * sin + (_height / 2) * cos);
    
    hd_x = (int)((_width / 2) * cos - (_height / 2) * sin);
    hd_y = (int)((_width / 2) * sin + (_height / 2) * cos);
    
    bg_x = (int)((-(_width / 2)) * cos - (-(_height / 2)) * sin);
    bg_y = (int)((-(_width / 2)) * sin + (-(_height / 2)) * cos);
    
    bd_x = (int)((_width / 2) * cos - (-(_height / 2)) * sin);
    bd_y = (int)((_width / 2) * sin + (-(_height / 2)) * cos);
    

     


    Je calcule les dimensions de la nouvelle image :

     

    int height, width;
    
    height = Math.Max(hg_y, Math.Max(hd_y, Math.Max(bg_y, bd_y))) * 2;
    width = Math.Max(hg_x, Math.Max(hd_x, Math.Max(bg_x, bd_x))) * 2;
    

     

     

     


    Et ici j'appelle ma fonction :

     

     

     

    //bmp est une reproduction de mon WriteableBitmap en bitmapImage
    //angle et mon angle calculé entre mes deux points
    
    wbCopy = GenerateConstrainedBitmap(bmp, width, height, angle);
    

     

     

     


    Et enfin ma fonction :

     

     

     

    private WriteableBitmap GenerateConstrainedBitmap(BitmapImage sourceImage, int pixelWidth, int pixelHeight, double rotation)
     {
      // _width et _height sont les dimensions d'origine de mon image
      double scale = CalculateConstraintScale(rotation, _width, _height);
    
      var transform = new TransformGroup();
      var rt = new RotateTransform()
      {
      Angle = rotation,
      CenterX = (pixelWidth/2 ),
      CenterY = (pixelHeight/2 )
      };
      transform.Children.Add(rt);
      var st = new ScaleTransform()
      {
      ScaleX = scale,
      ScaleY = scale,
      CenterX = (_width/2 ),
      CenterY = (_height/2)
      };
      transform.Children.Add(st);
    
      var tempImage = new Image()
      {
      Stretch = Stretch.Fill,
      Width = _width,
      Height = _height,
      Source = sourceImage,
      };
    
      tempImage.UpdateLayout();
    
      var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
      writeableBitmap.Render(tempImage, transform);
      writeableBitmap.Invalidate();
      return writeableBitmap;
    
     }
    

     

     

     

     

    J'ai essayé plusieurs "combinaison" en remplaçant à différent endroit _width et _height par pixelWidth et pixelHeight (et inversement) mais je n'arrive jamais à avoir les coins de mon image d'origine sur les bords de ma nouvelle image et mon points que je replace se retrouve donc à une position totalement différente de là ou il était à l'origine.

    J'ai essayé d'utiliser la class TransformedBitmap qui aurai pu (je pense) résoudre mon problème mais impossible de s'en servir...

    Si quelqu'un à une idée là je suis preneur !

    Merci d'avance !!

     



    vendredi 26 août 2011 08:33