将字节数组中的.ico转换为.net中的Image对象时出现问题

时间:2010-09-26 23:08:20

标签: .net gdi+

我正在尝试使用favicons并将它们添加到我正在创建的动态图像中。见StackFlair。网站代码在本地工作正常,并在一个共享托管服务器上。 blah blah,免费托管计划,你得到你支付的费用,等等等等。我的麻烦是我从新的托管设置中得到一个例外。 此异常只发生在.ico文件中。我可以在我测试过的所有服务器上处理.gif和.png图像(例如,一个gravatar图像)。我尝试使用的favicon是来自SE网络的favicons,但即使http://www.google.com/favicon.ico也会导致以下异常。

  

System.ArgumentException:参数无效。

     
      
  • System.Drawing.Image.FromStream(Stream stream,Boolean useEmbeddedColorManagement,Boolean validateImageData)
  •   
  • System.Drawing.Image.FromStream(Stream stream)
  •   

我正在尝试的代码变体如下。对于所有变体,我得到相同的参数无效异常。

byte[] imageBytes = //pull from Image field in SQL Server
//or
byte[] imageBytes = new WebClient().DownloadData(imageUrl);


MemoryStream ms = new MemoryStream(imageBytes);
Image image = Image.FromStream(ms);
 //or
Icon icon = new Icon(ms);
Image image = icon.ToBitmap();
//or
Image image = new Bitmap(ms);

所有这些在本地和坏主机服务器上工作得很好。它们都不能在我想要的服务器上运行。通过使用Trace输出,我可以验证数组的长度是否包含正确的字节数。如果我执行以下操作,则会看到图像按预期显示。

Response.Clear();
Response.BinaryWrite(imageBytes);
Response.End();

如果我循环遍历数组并写出每个字节值,那么从我的本地实例到我得到异常的服务器的输出是相同的。

如果有帮助,我的代码不起作用的服务器是带有sp2的Windows 2003服务器。

显然,框架告诉我字节流无效,但是我检查过的所有内容都会检出。关于为什么这个特定服务器在.ico文件上窒息的任何想法?

6 个答案:

答案 0 :(得分:2)

我有一个解决方法。使用ImageMagick将ico文件转换为png文件:

convert favicon.ico[0] favicon.png

然后这些很容易合作。 ImageMagick预先安装在许多共享主机上,或者您可以下载适用于Windows的预编译二进制文件。

如果您不使用[0],那么如果.ico文件中存储了多个图标图像,您将获得一系列文件favicon-0.png favicon-1.png等。然后,您需要对它们进行排序,选择最接近您想要的那个:16x16,具有Alpha透明度。 (我的favicon文件中包含32x32和48x48,适用于将互联网快捷方式拖到桌面上的IE用户。)ImageMagick在转换为png时保留了透明度。

stackapps.com/favicon.ico齿轮图标有两个图像。第一个具有alpha透明度,并且在浅灰色#DBDCDB背景上看起来很棒。

我假设您正在构建一个动态图像,如服务器上的http://i.stack.imgur.com/SNHfF.png,而不是将所有6个顶级站点图标发送到浏览器。如果没有,发送转换为png的图标仍然是一个好主意,因为它们不是为在网页内呈现而设计的。

...汤姆

答案 1 :(得分:1)

我已在Windows Server 2003 SP2上重现了您的问题并成立了解决方案。您的错误是在使用HTTP时进行响应,因此您应该提供响应内容类型。 我还在响应标题中添加了“content-disposition” - 但是没有关系,也没有要求 - 我只是用它来通过浏览器测试服务器响应。

// Part #1: Server
// read ico - you can make it in your manner
Stream fileStream = File.OpenRead( Server.MapPath( @"~\images\myicon.ico" ) );
byte[] fileBytes = new byte[ fileStream.Length ];
fileStream.Read( fileBytes, 0, (int) fileStream.Length );

// here is making response
Response.ContentType = "application/ico";
Response.AddHeader( "content-disposition", string.Format( "attachment;filename=myico.ico" ) );
Response.BinaryWrite( fileBytes );
Response.End();

和服务器部分

// Part#2: Client ( seems same as your )
WebClient client = new WebClient();
byte[] bytes = client.DownloadData( @"http://my url - you can't use it" );
MemoryStream ms = new MemoryStream(bytes);

Icon icon = new Icon( ms );
Image image = icon.ToBitmap();         // 1st way
Image yetOneImage = new Bitmap( ms );  // 2nd way

// or just put your url into browser and preview with your default images viewer

我希望它可以帮到你。

答案 2 :(得分:0)

我们在Media Browser中遇到了ico文件的问题。我记得它发生了,因为GDI +在其中包含PNG的图标上窒息,剥离它们修复它。或者在Vista上应用:http://support.microsoft.com/kb/971644修复它。

服务器2003可能有类似的补丁。

答案 3 :(得分:0)

只是一个想法:你确定你没有弄乱任何涉及的流吗?

我知道GDI +不喜欢在它完成之前关闭一个流,并且在这些情况下错误总是没有用。

您是否有完整的重新编码,以便我们完全帮助您?

答案 4 :(得分:0)

文档中有一条关于在图像生命周期内保持流打开的说明。这可能是问题吗?

http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx

  

你必须保持流开放   图像的生命周期。

     

如果这样,流将重置为零   方法被连续调用   同样的流。

答案 5 :(得分:0)

这里有一个非常干净详细的项目,用于从文件中提取多个图标: http://www.codeproject.com/Articles/6171/Access-multiple-icons-in-a-single-icon-file

我添加了这个功能:

Private Sub readIcoFromWebLink(ByVal link As Uri)

    ' Create the byte array and read it in
    '
    Dim byteArray() As Byte = New WebClient().DownloadData(link)

    ' Load the stream with the bytearray
    '
    icoStream = New MemoryStream(byteArray)
    icoStream.Seek(0, SeekOrigin.Begin)

End Function

并将改变者改为:

Public Sub New(ByVal filename As String)
    If IO.File.Exists(filename) Then
        readIcoFile(filename)                  ' Load the file
    Else
        readIcoFromWebLink(New Uri(filename))
    End If
    icoHeader = New iconHeader             ' Read the header

    Dim counter As Integer                 ' Read each icons header
    For counter = 1 To icoHeader.Count
        icons.Add(New iconEntry(counter - 1))
    Next
End Sub

添加对multiIcon类中的网络链接加载图标的支持。