2009-05-14 5 views
0

이미지를 배경에로드하는 중입니다. 이미지의 크기와 상관없이 이미지 크기 (또는 최대 또는 최소값)로 크기를 조정할 수있는 실버 캔버스가 필요합니다. 제대로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; 
      }); 
     } 
    } 

키는이 라인이었다

Dispatcher.BeginInvoke (대리인() {...} )에 대한 호출; 너비/높이가 이되기 전에 필요하며 간헐적으로 0이 일 수 있습니다.

1

당신은 아마 확실 실버 라이트 레이아웃을 업데이트 할 수있는 기회를 가지고 있는지 확인하기 위해 하나의 UI 루프주기를 기다려야한다. 또한 이미지가 실제로 표시되는지 확인해야합니다. 사실 이미지 바이너리에서 이미지 크기를 얻는 작은 루틴을 작성했습니다. 단점은 웹 클라이언트를 통해 명시 적으로 이미지를 다운로드해야하지만 좋은 점은 당신이 실제로 아무것도 표시하지 않고 크기를 알 수 있습니다 :

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

너비/높이 대신 backgroundImage.ActualWidth/Height를 사용해 보셨습니까? –

+0

네, 그 사람들은 제가 두려워하는 데 도움이되지 않았습니다. – aronchick

관련 문제