2009-05-14 11 views
0

Ich lade ein Bild in einen Hintergrund, und ich möchte, dass die Silverlight-Leinwand, die alles enthält, die Größe der Bildgröße (oder des von mir bestimmten Maximums oder Minimums) der Größe des Bildes ändert. Also habe ich getan, um das folgende:Wie kann ich die Größe eines geladenen Bildes mit Silverlight 2 ermitteln?

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

das Bild korrekt geladen, aber egal, wo ich scheine die backgroundImage.Height/Breite (off .Loaded Ereignis zu setzen, .SizeChanged Ereignis [1], Mit einer Grenze [2] usw.), gibt es immer 0.0 oder NaN zurück. Was mache ich falsch?

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

Antwort

2

Ah, Lösung! 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; 
      }); 
     } 
    } 

Der Schlüssel war diese Linie:

Der Aufruf von Dispatcher.BeginInvoke (Delegate() {... }); ist erforderlich, bevor Sie die Breite/Höhe erhalten, oder sie intermittierend Null sein können.

1

Sie müssen wahrscheinlich eine UI-Schleifenzyklus warten, um sicherzustellen, dass Silverlight eine Chance hat, Layout zu aktualisieren. Außerdem müssen Sie sicher sein, dass das Bild tatsächlich sichtbar ist. Ich habe eigentlich eine kleine Routine geschrieben, die die Bildgröße aus Bild binär bekommt. Nachteil ist, dass Sie Bild explizit über WebClient herunterladen müssen würden aber die gute Sache ist, dass Sie Dimensionen wissen werden, ohne tatsächlich etwas Anzeige:

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

Hoffnung, das hilft.

+0

das ist sehr beeindruckend! Aber ist es nicht ein wahnsinniger Overkill für ein scheinbar einfaches Problem? Ich muss nicht einmal wirklich die Größe wissen, in der Wahrheit, alles was ich wirklich brauche, ist die Leinwand richtig zu dimensionieren. – aronchick

+0

Haben Sie versucht, backgroundImage.ActualWidth/Height anstelle von Width/Height zu verwenden? –

+0

ja, diese haben mir nicht geholfen, ich habe Angst. – aronchick

Verwandte Themen