2009-05-14 2 views
0

イメージをバックグラウンドにロードしています。イメージのサイズに関係なく、イメージサイズ(または最大値または最小値)にリサイズするSilverlightキャンバスが必要です。正しく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; 
     } 
    } 

画像が読み込まれると、私はbackgroundImage.Height /幅を置くように見えるかかわらず(.Loadedイベントオフ、.SizeChangedイベントは、[1]、境界線を使用:だから私は、次のことをやりました[2]など)、常に0.0またはNaNを返します。私は間違って何をしていますか?

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

答えて

2

ああ、解決策! 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; 
      }); 
     } 
    } 

KEYこのラインであった:

Dispatcher.BeginInvoke(デリゲート(){...} )へのコール。幅/高さが になる前に必要です。または、断続的にゼロである になることがあります。

1

をあなたはおそらくSilverlightがレイアウトを更新する機会を持っていることを確認するために、1つのUIループサイクルを待たなければなりません。また、画像が実際に見えることを確認する必要があります。私は実際にイメージバイナリからイメージサイズを取得する小さなルーチンを書いた。欠点は、あなたがWebクライアントを経由して明示的にイメージをダウンロードする必要がありますですが、良いことは、あなたが実際には何も表示せずに寸法を知っているよです:

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

希望はこのことができます。

+0

これは非常に印象的です!それはかなり簡単な問題のように思えるもののために狂った過剰なものではありませんか?私は本当にサイズを知る必要はありません、実際には、本当に必要なのは、キャンバスを正確にサイズ調整することだけです。 – aronchick

+0

Width/Heightの代わりにbackgroundImage.ActualWidth/Heightを使用しようとしましたか? –

+0

はい、それらは私が恐れることを助けませんでした。 – aronchick

関連する問題