代码之家  ›  专栏  ›  技术社区  ›  Rebecca Chernoff

将字节数组中的.ico转换为.NET中的图像对象时出现问题

  •  12
  • Rebecca Chernoff  · 技术社区  · 14 年前

    我试着把这些假象加在我正在创建的动态图像中。见 StackFlair . 网站代码在本地和一个共享的主机服务器上工作正常。 废话废话,免费的托管计划,你得到你支付的,废话 我的问题是我从一个新的主机设置中得到一个异常。 此异常仅适用于.ico文件。 我可以在我测试过的所有服务器上处理.gif和.png图像(即gravatar图像)。我尝试使用的是来自SE网络的传真,但甚至 http://www.google.com/favicon.ico 导致以下异常。

    System.ArgumentException:参数无效。

    • system.drawing.image.fromstream(流,布尔型useEmbeddedColorManagement,布尔型validateImageData)
    • system.drawing.image.fromstream(流)

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

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

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

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

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

    如果有帮助的话,我的代码不起作用的服务器是带有SP2的Windows2003服务器。

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

    6 回复  |  直到 9 年前
        1
  •  2
  •   Tom Robinson    14 年前

    我有个变通办法。使用ImageMagick将ICO文件转换为PNG文件:

    convert favicon.ico[0] favicon.png
    

    那么这些很容易使用。ImageMagick预安装在许多共享主机上,或者您可以下载Windows的预编译二进制文件。

    如果不使用[0],则如果.ico文件中存储了多个图标图像,则将获得一系列文件favicon-0.png favicon-1.png等。然后,您将需要对它们进行排序,以选择最接近您想要的:16x16和阿尔法透明度。(我在Favicon文件中包括32x32和48x48,用于将Internet快捷方式拖动到桌面的IE用户。)ImageMagick在转换为PNG时保持透明度。

    stackapps.com/favicon.ico gear图标有两个图像。第一个具有阿尔法透明度,在浅灰色的DBDCDB背景上看起来很不错。

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

    汤姆……

        2
  •  1
  •   mastak    14 年前

    我已在Windows Server 2003 SP2上复制了您的问题并建立了解决方案。您的错误是在使用HTTP时做出响应,因此应该提供响应内容类型。 另外,我在响应头中添加了“内容部署”,但这并不重要,也不是必需的,我只是使用它通过浏览器测试服务器响应。

    // 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
    

    希望对你有帮助。

        3
  •  0
  •   Sam Saffron James Allen    14 年前

    我们的ICO文件有问题 Media Browser 我记得这是因为GDI+被图标阻塞了,图标上有PNG,把它们去掉,修复了它。或申请: http://support.microsoft.com/kb/971644 在Vista上修复了它。

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

        4
  •  0
  •   Simon Mourier    14 年前

    只是想一想:你确定你没有弄乱任何相关的信息流吗?

    我知道gdi+不喜欢在流完成之前关闭它,在这些情况下,错误总是不太有用。

    你能给我一个准确的重印码吗?这样我们就能帮到你了。

        5
  •  0
  •   wes    14 年前

    在文档中有一条关于在图像的生命周期中保持流打开的注释。这就是问题所在吗?

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

    您必须保持流为 图像的生存期。

    如果这样,流将重置为零 方法是用 同一条河流。

        6
  •  0
  •   Mojtaba Rezaeian    9 年前

    这里有一个非常干净和详细的项目,用于从文件中提取多个图标: 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
    

    并将construnctor更改为:

    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
    

    在中添加对从Web链接加载图标的支持 multiIcon 班级。