ASP.NET libwebp.dll如何将WebP图像保存到磁盘?

8
我已根据这些说明(我下载了源代码)构建了WebP的libwebp.dll
我将libwebp.dll文件添加到了我的项目的bin文件夹中。
然后,我添加了这段代码(在此处找到):
Private Declare Function WebPEncodeBGRA Lib "libwebp.dll" (ByVal rgba As IntPtr, ByVal width As Integer, ByVal height As Integer, ByVal stride As Integer, ByVal quality_factor As Single, ByRef output As IntPtr) As Integer
Private Declare Function WebPFree Lib "libwebp.dll" (ByVal p As IntPtr) As Integer

Private Sub Encode()
    Dim source As Bitmap = New Bitmap(Server.MapPath("images\") + "audio.png")
    Dim data As BitmapData = source.LockBits(New Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
    Dim webp_data As IntPtr
    Dim i As Integer = WebPEncodeBGRA(data.Scan0, source.Width, source.Height, data.Stride, 80, webp_data)

    WebPFree(webp_data)
End Sub

我遇到了以下错误:

尝试加载具有不正确格式的程序。 (来自 HRESULT 的异常: 0x8007000B)

以下是我采取的措施(在 Dai 的评论之后):

  • 我按如下方式构建了一个针对64位架构的dll:nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output ARCH=x64此处也可参考
  • 我检查了应用程序池的IIS,并将其属性Enable32-Bit Applications设置为False
  • 我正在运行 Windows 10 64位版本
  • 在代码后端,Environment.Is64BitProcessEnvironment.Is64BitOperatingSystem均评估为True

如何将图像编码并以WebP格式保存编码后的图像到磁盘上?

这是我使用的图像文件:

enter image description here


错误是由尝试在64位主机进程中加载32位DLL或反之而来。我假设你的Web服务器正在以64位运行,但你只构建了32位版本的 libwebp.dll - Dai
有可能是相反的情况:IIS以32位运行,无法加载您的64位DLL。 - Dai
我刚刚检查了IIS中有关该应用程序池的应用程序池设置,发现其属性“Enable32-Bit Applications”被设置为“False”,所以我猜那也不是问题的原因... - Adam
2个回答

5

我该如何将图像进行编码,并以WebP格式保存已编码的图像到磁盘上?

转换过程后,您需要对非托管内存进行编组,以便在托管代码中使用数据。

Public Sub Encode()
    Dim source As Bitmap = New Bitmap(Server.MapPath("images\audio.png"))
    'Hold bitmap data
    Dim bmpData As BitmapData = source.LockBits(New Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)

    'Create a pointer for webp data
    Dim webpDataSrc As IntPtr

    'Store resulting webp data length after conversion
    Dim webpDataLen As Integer = WebPEncodeBGRA(bmpData.Scan0, source.Width, source.Height, bmpData.Stride, 80, webpDataSrc)

    'Create a managed byte array with the size you just have
    Dim webpDataBin As Byte() = New Byte(webpDataLen - 1){}

    'Copy from unmanaged memory to managed byte array you created
    System.Runtime.InteropServices.Marshal.Copy(webpDataSrc, webpDataBin, 0, webpDataLen)

    'Write byte array to a file
    System.IO.File.WriteAllBytes(Server.MapPath("images\audio.webp"), webpDataBin)

    'Free
    WebPFree(webpDataSrc)

    source.Dispose()
End Sub

顺便提一下,您所使用的命令 nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output ARCH=x64 是可行的。我也可以用这个命令编译库(版本1.0.0)。但是我十分确定,这里压缩的 libwebp.dll是32位的,而不是64位的。

请确保您启动了正确的环境以生成64位二进制文件。


好的...看起来这样保存了webp图像!最后一步:你是在哪个环境下创建64位二进制文件的?我尝试过x64 Native Tools Command Prompt for Visual Studio 2017,也尝试过我的常规Windows命令提示符,它正在64位模式下运行,还尝试过Windows Powershell。但是这些都对我不起作用。 - Adam
@Flo 和你使用的是相同的环境和命令。这是一个dumpbin输出的目录截图:https://img.imgur.com/5BXzyuN.png - Kul-Tigin
好的...这让我疯了...你能把你编译的64位dll分享给我吗?然后我可以关闭这个线程,颁发奖励,接着弄清楚为什么它在我的机器上不起作用...非常感谢! - Adam
嗯...我本想在SO上将奖励分给你和另一个发帖者,但这是不可能的。由于另一个发帖者先到并提供了关键部分——webp编码失败的解决方案,我将授予他奖励,并为你开启另一个奖励以授予你50个积分...希望你能理解 :-) - Adam
2
@Flo 没问题,但是对我来说额外的赏金并不是必要的。谢谢。 - Kul-Tigin
糟糕...原来额外的赏金比起一开始还要更高...很高兴你能接受,感谢你的帮助! :-) - Adam

4
我也遇到了与您的示例相关的问题,所以我查看了源代码,发现您使用的方法与示例不同,不知道为什么。
于是我进行了更改,现在看起来可以工作了。
    <DllImport("libwebp.dll", CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function WebPEncodeBGRA(ByVal rgba As IntPtr, ByVal width As Integer, ByVal height As Integer, ByVal stride As Integer, ByVal quality_factor As Single, <Out> ByRef output As IntPtr) As Integer
End Function


<DllImport("libwebp.dll", CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function WebPFree(ByVal p As IntPtr) As Integer
End Function

并且导入

Imports System.Runtime.InteropServices

我使用了从这些指令下载的libwebp-0.6.0.zip\x64\bin中的dll,并且它能正常工作。
当我试图附上你的dll时,从这里下载已编译和压缩的libwebp.dll。这是我正在使用的图像文件:
我得到了完全相同的异常,看起来不是64位的。
对于图片,我不确定,可能需要反转它。
            'data.strinde = webp_data 'not sure what is webp_data ewxacly, but you can check
        'data.Scan0 = webp_data 'not sure what is webp_data ewxacly, but you can check
        source.UnlockBits(data)
        source.Save(Server.MapPath("images\") + "audio.png")

谢谢,0.6.0的dll似乎确实有助于解决第一个错误。您正在保存“source”变量,但需要保存“webp_data”变量,我该如何做呢?您能否为x64编译1.0.0的“libwebp.dll”?我不想使用0.6.0 beta版本,也不知道为什么无法正确编译。 - Adam
你好!再次感谢你的帮助。我现在遇到了错误 There is insufficient system memory in resource pool 'internal' to run this query.,我猜测是因为我没有清除内存。我看到你代码中的 WebPFree 方法是空的,你知道我应该输入什么来清除内存吗? - Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接