如何在Silverlight Image控件上显示TIFF(以Byte[]的形式)

发布于 2024-11-09 06:29:24 字数 2339 浏览 0 评论 0 原文

我创建了一个窗口服务,将所有 TIFF 文件放入数据库并将它们存储为 Byte[]

现在我希望能够通过 Silverlight 图像控件显示它们

,因此我在绑定 XAML 期间使用转换器,以便将 Byte[] 转换为 Bitmap 因为 Image.Source 仅接受其 URI(我没有将文件存储在服务器上,因此无法使用此方法)或 Bitmap

BitmapImage bmi = new BitmapImage();
if (value != null)
{
    ImageGallery imageGallery = value as ImageGallery;
    byte[] imageContent = imageGallery.ImageContent;
    string imageType = imageGallery.ImageType;
    using (MemoryStream ms = new MemoryStream(imageContent))
    {
        bmi.SetSource(ms);
    }
}
return bmi;

但是,我在 bmi.SetSource(ms) 处遇到异常,因为 Silverlight 仅支持 JPEG 和 PNG 图像。

所以我做了更多的研究,知道我应该将 TIFF 的字节转换为 JPEG 或 PNG 的字节,然后它就可以工作了。

为此,我尝试了两种方法:

  • 在服务器上进行转换:在我的 RIA 服务调用中,检索 ImageGallery 后,我循环遍历可用图像,将 TIFF 字节转换为 JPEG 字节。

但这不起作用...... 你能告诉我我哪里做错了吗?

public IQueryable<ImageGallery> GetImageGalleries()
{
    var imageGalleries = this.ObjectContext.ImageGalleries.OrderBy(i=>i.ImageName);
    foreach (ImageGallery imageGallery in imageGalleries)
    {
        if (imageGallery.ImageType == ".tif" || imageGallery.ImageType == ".tiff")
        {
            //Convert the Tiff byte array format into JPEG stream format
            System.Drawing.Bitmap dImg = new System.Drawing.Bitmap(new MemoryStream(imageGallery.ImageContent));
            MemoryStream ms = new MemoryStream();
            dImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            //then convert the JPEG stream format into JPEG byte array format
            byte[] buf = new byte[ms.Length];  
            ms.Read(buf, 0, buf.Length);

            //Changing the format tiff byte[] of ImageGallery to jpeg byte[] 
            imageGallery.ImageContent = buf;
        }
    }
    return imageGalleries;
}
  • 另一种解决方案是使用 LibTiff.Net 库直接转换 Byte[]直接在 Silverlight 上将 TIFF 转换为 WritableBitmap

然而,在深入研究他们的示例应用程序或使用 Reflector 查看源代码函数后,我仍然不知道如何使用他们的库将 TIFF 字节转换为 WritableBitmap JPEG(或 PNG)因为他们的示例仅显示使用在文件目录中搜索 TIFF 的 API。就我而言,服务器上没有现有文件。

有人可以帮我如何在 Silverlight 的图像控件上显示 TIFF 文件吗?

我搜索了论坛,但没有找到任何可靠的答案。

谢谢

I created a window service to put all of my TIFF files into database and stored them as Byte[].

Now I want to be able to display them through Silverlight Image control

So i use the Converter during binding XAML in order to convert the Byte[] to Bitmap because the Image.Source only accept eitheir URI (I don't have the file stored on server so can't use this method) or Bitmap.

BitmapImage bmi = new BitmapImage();
if (value != null)
{
    ImageGallery imageGallery = value as ImageGallery;
    byte[] imageContent = imageGallery.ImageContent;
    string imageType = imageGallery.ImageType;
    using (MemoryStream ms = new MemoryStream(imageContent))
    {
        bmi.SetSource(ms);
    }
}
return bmi;

However, I get the exception at bmi.SetSource(ms) because Silverlight only supports JPEG and PNG images.

So I did more research and knew that i should convert the bytes of TIFF to bytes of JPEG or PNG then it will work.

To do that I tried two methods:

  • Doing the conversion on server: in my RIA service call, after retrieving the ImageGallery, I loop through the available image to convert the bytes of TIFF to the bytes of JPEG.

BUT IT DOESN'T WORK....
Can you tell me where I did wrong?

public IQueryable<ImageGallery> GetImageGalleries()
{
    var imageGalleries = this.ObjectContext.ImageGalleries.OrderBy(i=>i.ImageName);
    foreach (ImageGallery imageGallery in imageGalleries)
    {
        if (imageGallery.ImageType == ".tif" || imageGallery.ImageType == ".tiff")
        {
            //Convert the Tiff byte array format into JPEG stream format
            System.Drawing.Bitmap dImg = new System.Drawing.Bitmap(new MemoryStream(imageGallery.ImageContent));
            MemoryStream ms = new MemoryStream();
            dImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            //then convert the JPEG stream format into JPEG byte array format
            byte[] buf = new byte[ms.Length];  
            ms.Read(buf, 0, buf.Length);

            //Changing the format tiff byte[] of ImageGallery to jpeg byte[] 
            imageGallery.ImageContent = buf;
        }
    }
    return imageGalleries;
}
  • The other solution is to use LibTiff.Net library to convert directly the Byte[] of TIFF to WritableBitmap directly on Silverlight.

However, after digging through their sample application or using Reflector to see the source code functions, I still can't figure out how to use their library to convert the bytes of TIFF to WritableBitmap JPEG (or PNG) because their sample only show the API for using the search the TIFF in a file directory. In my case, I don't have an existing file on server.

Can someone help me how to show the TIFF file on Image control of Silverlight?

I searched the forum but didn't find any solid answer for this.

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

并安 2024-11-16 06:29:24

我认为 LibTiff 将是最佳选择。最终,Tiff.ClientData 接受作为 tiff 数据的 Stream。如果您的 tiff 数据确实是一个 byte[] 那么您只需要一个 MemoryStream 围绕它。更有可能的是,在某个时刻,byte[] 是从流中提取的,因此您可能甚至不需要这个中介 byte[] / MemoryStream

I think the LibTiff will be the way to go. Ulitmately the Tiff.ClientData accepts a Stream that is the tiff data. If your tiff data really is a byte[] then you just need a MemoryStream around it. More likely at some point the byte[] is pulled from a stream so you probably don't even need this intermedatory byte[] / MemoryStream.

水水月牙 2024-11-16 06:29:24
  1. 参考 LibTiff.net

  2. 添加此类:

    使用系统;
    使用 System.Collections.Generic;
    使用系统.IO;
    使用 System.Windows.Media.Imaging;
    使用 BitMiracle.LibTiff.Classic;
    
    命名空间 CoreTechs.X9
    {
        公共静态类 TiffUtility
        {
            公共静态Tiff CreateTiff(此字节[]字节)
            {
                MemoryStream ms = new MemoryStream(字节);
                Tiff tiff = Tiff.ClientOpen("内存中", "r", ms, new TiffStream());
                返回 TIFF;
            }
    
            公共静态 IEnumerable; ConvertToWriteableBitmaps(此 Tiff tiff)
            {
                如果(tiff == null)
                    throw new ArgumentNullException("tiff", "tiff 为空。");
    
                短目录 = tiff.NumberOfDirectories();
    
                for (int i = 0; i < 目录; i++)
                {
                    if (tiff.SetDirectory((short)i))
                    {
                        inttileCount = tiff.NumberOfTiles();
                        int stripCount = tiff.NumberOfStrips();
    
                        varframeWidthField = tiff.GetField(TiffTag.IMAGEWIDTH);
                        varframeHeightField = tiff.GetField(TiffTag.IMAGELENGTH);
                        var compressionField = tiff.GetField(TiffTag.COMPRESSION);
                        var xResolutionField = tiff.GetField(TiffTag.XRESOLUTION);
                        var yResolutionField = tiff.GetField(TiffTag.YRESOLUTION);
                        var SamplesPerPixelField = tiff.GetField(TiffTag.SAMPLESPERPIXEL);
    
                        intframeWidth =frameWidthField != null &&帧宽度字段.长度> 0 ? frameWidthField[0].ToInt() : 0;
                        intframeHeight=frameHeightField!=null&&框架高度字段.长度> 0 ? FrameHeightField[0].ToInt() : 0;
                        var 压缩 = 压缩字段 != null &&压缩字段.长度> 0 ? (压缩)compressionField[0].Value : Compression.NONE;
                        var xResolution = xResolutionField != null && xResolutionField.Length > 0 ? new double?(xResolutionField[0].ToDouble()) : null;
                        var yResolution = yResolutionField != null && yResolutionField.Length > 0 ? new double?(yResolutionField[0].ToDouble()) : null;
                        var SamplesPerPixel = SamplesPerPixelField != null && SamplesPerPixelField.Length > 0 ? SamplesPerPixelField[0].ToString() : String.Empty;
    
                        if (xResolution != null && yResolution == null)
                        {
                            y 分辨率 = x 分辨率;
                        }
    
                        var buffer = new int[frameWidth * frameHeight];
                        tiff.ReadRGBAImage(frameWidth、frameHeight、缓冲区);
    
                        var bmp = new WriteableBitmap(frameWidth,frameHeight);
                        for (int y = 0; y < 框架高度; y++)
                        {
                            var ytif = y * 帧宽度;
                            var ybmp = (frameHeight - y - 1) *frameWidth;
    
                            for (int x = 0; x < 帧宽度; x++)
                            {
                                var currentValue = buffer[ytif + x];
    
                                // 将 Tiff 的 RGBA 格式转换为 Silverlight WriteableBitmap 的 ARGB 格式
                                bmp.Pixels[ybmp + x] = Tiff.GetB(currentValue) | bmp.Pixels[ybmp + x] = Tiff.GetB(currentValue) | Tiff.GetG(currentValue) << 8 | Tiff.GetR(currentValue) << 16 | 16 Tiff.GetA(currentValue) << 24;
                            }
                        }
    
                        产量返回bmp;
                    }
                }
            }
        }
    }
    
  3. 使用如下扩展方法:

    byte[] myHappyTiffData = GetMyTiffBytesFromSomewhere();
    WriteableBitmap bmp = myHappyTiffData.CreateTiff().ConvertToWriteableBitmaps().FirstOrDefault();
    myImageControl.Source = bmp;
    
  1. Reference LibTiff.net

  2. Add this class:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Windows.Media.Imaging;
    using BitMiracle.LibTiff.Classic;
    
    namespace CoreTechs.X9
    {
        public static class TiffUtility
        {
            public static Tiff CreateTiff(this byte[] bytes)
            {
                MemoryStream ms = new MemoryStream(bytes);
                Tiff tiff = Tiff.ClientOpen("in-memory", "r", ms, new TiffStream());
                return tiff;
            }
    
            public static IEnumerable<WriteableBitmap> ConvertToWriteableBitmaps(this Tiff tiff)
            {
                if (tiff == null)
                    throw new ArgumentNullException("tiff", "tiff is null.");
    
                short dirs = tiff.NumberOfDirectories();
    
                for (int i = 0; i < dirs; i++)
                {
                    if (tiff.SetDirectory((short)i))
                    {
                        int tileCount = tiff.NumberOfTiles();
                        int stripCount = tiff.NumberOfStrips();
    
                        var frameWidthField = tiff.GetField(TiffTag.IMAGEWIDTH);
                        var frameHeightField = tiff.GetField(TiffTag.IMAGELENGTH);
                        var compressionField = tiff.GetField(TiffTag.COMPRESSION);
                        var xResolutionField = tiff.GetField(TiffTag.XRESOLUTION);
                        var yResolutionField = tiff.GetField(TiffTag.YRESOLUTION);
                        var samplesPerPixelField = tiff.GetField(TiffTag.SAMPLESPERPIXEL);
    
                        int frameWidth = frameWidthField != null && frameWidthField.Length > 0 ? frameWidthField[0].ToInt() : 0;
                        int frameHeight = frameHeightField != null && frameHeightField.Length > 0 ? frameHeightField[0].ToInt() : 0;
                        var compression = compressionField != null && compressionField.Length > 0 ? (Compression)compressionField[0].Value : Compression.NONE;
                        var xResolution = xResolutionField != null && xResolutionField.Length > 0 ? new double?(xResolutionField[0].ToDouble()) : null;
                        var yResolution = yResolutionField != null && yResolutionField.Length > 0 ? new double?(yResolutionField[0].ToDouble()) : null;
                        var samplesPerPixel = samplesPerPixelField != null && samplesPerPixelField.Length > 0 ? samplesPerPixelField[0].ToString() : String.Empty;
    
                        if (xResolution != null && yResolution == null)
                        {
                            yResolution = xResolution;
                        }
    
                        var buffer = new int[frameWidth * frameHeight];
                        tiff.ReadRGBAImage(frameWidth, frameHeight, buffer);
    
                        var bmp = new WriteableBitmap(frameWidth, frameHeight);
                        for (int y = 0; y < frameHeight; y++)
                        {
                            var ytif = y * frameWidth;
                            var ybmp = (frameHeight - y - 1) * frameWidth;
    
                            for (int x = 0; x < frameWidth; x++)
                            {
                                var currentValue = buffer[ytif + x];
    
                                // Shift the Tiff's RGBA format to the Silverlight WriteableBitmap's ARGB format
                                bmp.Pixels[ybmp + x] = Tiff.GetB(currentValue) | Tiff.GetG(currentValue) << 8 | Tiff.GetR(currentValue) << 16 | Tiff.GetA(currentValue) << 24;
                            }
                        }
    
                        yield return bmp;
                    }
                }
            }
        }
    }
    
  3. Use the exension methods like this:

    byte[] myHappyTiffData = GetMyTiffBytesFromSomewhere();
    WriteableBitmap bmp = myHappyTiffData.CreateTiff().ConvertToWriteableBitmaps().FirstOrDefault();
    myImageControl.Source = bmp;
    
故事未完 2024-11-16 06:29:24

我们首先将 LibTiff 作为媒体经理的解决方案。我不会推荐它。

正如您所看到的,它为每个页面创建一个 WriteableBitmap。 WB 是您可以在 Silverlight 中使用的最阻碍性能、泄漏的对象,因此,如果您有超过 1 个单页 tiff,您的应用程序将更快地耗尽内存,然后您可以说 Avada Kedavra。

有些观众似乎可以在不杀死您的应用程序(以及浏览器和计算机)的情况下加载大型多页 tiff,只需支付相当多的许可费,但目前我没有任何东西可以让您解码 tiff 并提取页面。

亚军:

We began with LibTiff as a solution for our media manager. I wouldn't recommend it.

As you can see it creates a WriteableBitmap for each page. WB is the most performance hampering, leaking object you can use in Silverlight, so if you got more then 1 single page tiff your app will run out of memory faster then you can say Avada Kedavra.

There are viewers that appearently can load a large multipage tiff without killing your app (and browser and computer), for a decent license fee, but at this point I got nothing that allows you to decode a tiff an extract the pages.

Runner ups:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文