2009-05-14 5 views
0

Je charge une image sur un arrière-plan, et je veux que le canevas argenté contenant tout soit redimensionné à la taille de l'image (ou au maximum ou au minimum que je détermine) quelle que soit la taille de l'image. Donc, je l'ai fait ce qui suit:Comment déterminer la taille d'une image chargée à l'aide de Silverlight 2?

private int ImageMargin = 4; 

    public Page() 
    { 
     InitializeComponent(); 

     BitmapImage bi = new BitmapImage(new Uri("1.jpg", UriKind.Relative)); 
     backgroundImage.Source = bi; 
     bi.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(bi_DownloadProgress); 

     backgroundImage.SizeChanged += new SizeChangedEventHandler(backgroundImage_SizeChanged); 

    } 

    void bi_DownloadProgress(object sender, DownloadProgressEventArgs e) 
    { 
     if (e.Progress == 100) 
     { 
      LayoutRoot.Height = backgroundImage.Height + ImageMargin * 2; 
      LayoutRoot.Width = backgroundImage.Width + ImageMargin * 2; 
     } 
    } 

L'image correctement charges, mais peu importe où je semble mettre le backgroundImage.Height/Largeur (hors événement .Loaded, événement .SizeChanged [1], en utilisant une frontière [2], etc), il renvoie toujours 0.0 ou NaN. Qu'est-ce que je fais mal?

[1] http://silverlight.net/forums/t/14855.aspx [2] http://silverlight.net/forums/t/90235.aspx

Répondre

2

Ah, solution! Silverlight Tip of the Day #13 - How to Get an Images Dimensions in Silverlight.

private Image image; 

    public Page() 
    { 
     InitializeComponent(); 
     LoadImage("image.png"); 
    } 

    private void LoadImage(string path) 
    { 

     Uri uri = new Uri(path, UriKind.Relative); 
     BitmapImage bitmapImage = new BitmapImage(); 
     bitmapImage.UriSource = uri; 
     bitmapImage.DownloadProgress += 
      new EventHandler<DownloadProgressEventArgs>(bitmapImage_DownloadProgress); 
    } 

    void bitmapImage_DownloadProgress(object sender, DownloadProgressEventArgs e) 
    { 
     if (e.Progress == 100) 
     { 
      Dispatcher.BeginInvoke(delegate() 
      { 
       double height = image.ActualHeight; 
       double width = image.ActualWidth; 
      }); 
     } 
    } 

La clé était cette ligne:

L'appel à Dispatcher.BeginInvoke (délégué() {...} ); est nécessaire avant d'obtenir le Largeur/Hauteur ou ils peuvent être par intermittence zéro.

1

Vous devez attendre probablement un cycle de boucle d'interface utilisateur pour vous assurer que Silverlight a une chance de mettre à jour mises en page. Aussi, vous devez être sûr que l'image est réellement visible. J'ai effectivement écrit une petite routine qui obtient la taille de l'image à partir de l'image binaire. Le seul inconvénient est que vous devrez télécharger l'image explicitement via WebClient, mais la bonne chose est que vous saurez les dimensions sans afficher quoi que ce soit:

namespace StatMap.Silverlight.Services.UIHelpers 
{ 
    public static class ImageSizeExtractor 
    { 
     public static bool TryGetImageSize(byte[] buf, out int width, out int height) 
     { 
      return TryGetPngSize(buf, out width, out height) || TryGetJpegSize(buf, out width, out height); 
     } 

     private static bool IsPng(byte[] buf) 
     { 
      return (buf.Length > 8)&&(buf[0] == 137) && (buf[1] == 80) && (buf[2] == 78) && (buf[3] == 71) 
        && (buf[4]==13)&&(buf[5]== 10)&&(buf[6]== 26)&&(buf[7]== 10); 
     } 

     private static bool TryGetPngSize(byte[] buf, out int width, out int height) 
     { 
      width = 0; 
      height = 0; 
      if (IsPng(buf)) 
      { 
       int index = -1; 
       for (int i = 8; i < buf.Length - 12;i++) 
       { 
        if ((buf[i]==0x49)&&(buf[i+1]==0x48)&&(buf[i+2]==0x44)&&(buf[i+3]==0x52)) 
        { 
         index = i + 4; 
         break; 
        } 
       } 

       if (index<0) 
       { 
        return false; 
       } 
       width = buf[index + 3] + buf[index + 2]*256; 
       height = buf[index + 7] + buf[index + 6]*256; 
       return true; 
      } 
      return false; 
     } 

     private static bool TryGetJpegSize(byte[] buf, out int width, out int height) 
     { 
      //static char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height) { 
      //Check for valid JPEG image 
      int i = 0; // Keeps track of the position within the file 
      width = 0; 
      height = 0; 
      if (buf[i] == 0xFF && buf[i + 1] == 0xD8 && buf[i + 2] == 0xFF && buf[i + 3] == 0xE0) 
      { 
       i += 4; 
       // Check for valid JPEG header (null terminated JFIF) 
       if (buf[i + 2] == 'J' && buf[i + 3] == 'F' && buf[i + 4] == 'I' && buf[i + 5] == 'F' && 
        buf[i + 6] == 0x00) 
       { 
        //Retrieve the block length of the first block since the first block will not contain the size of file 
        int blockLength = buf[i]*256 + buf[i + 1]; 
        while (i < buf.Length) 
        { 
         i += blockLength; //Increase the file index to get to the next block 
         if (i >= buf.Length) return false; //Check to protect against segmentation faults 
         if (buf[i] != 0xFF) return false; //Check that we are truly at the start of another block 
         if (buf[i + 1] == 0xC0) 
         { 
          //0xFFC0 is the "Start of frame" marker which contains the file size 
          //The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y] 
          width = buf[i + 5]*256 + buf[i + 6]; 
          height = buf[i + 7]*256 + buf[i + 8]; 
          return true; 
         } 
         i += 2; //Skip the block marker 
         blockLength = buf[i]*256 + buf[i + 1]; //Go to the next block 
        } 
        return false; //If this point is reached then no size was found 
       } 
       return false; 
      } 
      return false; 
     } 
    } 
} 

Hope this helps.

+0

c'est très impressionnant! mais n'est-ce pas exagéré pour ce qui semble être un problème assez simple? Je n'ai même pas vraiment besoin de connaître la taille, en vérité, tout ce dont j'ai vraiment besoin est de dimensionner la toile correctement autour. – aronchick

+0

Avez-vous essayé d'utiliser backgroundImage.ActualWidth/Height au lieu de Width/Height? –

+0

oui, ceux qui n'ont pas aidé j'ai peur. – aronchick

Questions connexes