如何使用Silverlight 2计算出加载图像的大小?

时间:2009-05-14 00:20:22

标签: c# silverlight

我正在将图像加载到背景中,我希望包含它的Silverlight画布全部调整为图像大小的图像大小(或我确定的最大值或最小值)。所以我做了以下事情:

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 / Width(关闭.Loaded事件,.SizeChanged事件[1],使用边框[2]等),它总是返回0.0或NaN的。我做错了什么?

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

2 个答案:

答案 0 :(得分: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(delegate(){...   });在获得之前需要   宽度/高度或它​​们可能是   间歇性地为零。

答案 1 :(得分:1)

您可能需要等待一个UI循环周期才能确保Silverlight有机会更新布局。此外,您必须确保图像实际可见。我实际上写了一个小例程,它从图像二进制文件中获取图像大小。下行是你必须通过WebClient明确下载图像,但好处是你会知道尺寸而不实际显示任何东西:

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

希望这有帮助。