ASP.NET libwebp.dll how to save WebP image to disk
Asked Answered
C

2

8

I've built libwebp.dll for WebP, using these instructions (I downloaded this source code)

I've added the libwebp.dll file to the bin folder of my project.

I then added this code (found here):

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

I get the error:

An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

What I also did (after comments from Dai below):

  • I built the dll for a 64-bit architecture like so: nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output ARCH=x64 (also see here)
  • I checked IIS for the application pool in question and it has the property Enable32-Bit Applications set to False
  • I'm running Windows 10 64 bit
  • Both Environment.Is64BitProcess and Environment.Is64BitOperatingSystem in code-behind evaluate as True

How can I encode the image and save the encoded image to disk in WebP format?

This is the image file I'm using:

enter image description here

Canty answered 28/4, 2018 at 15:24 Comment(3)
The error is caused by attempting to load a 32-bit DLL in a 64-bit host process or vice-versa. I'm assuming your web-server is running as 64-bit but you only built the 32-bit version of libwebp.dll.Genie
It's possible it's the other way around: that IIS is running as 32-bit and it cannot load your 64-bit DLL.Genie
I just checked the Application Pool settings in IIS for the application pool in question and it has the property Enable32-Bit Applications set to False, so I guess that's not it either...Canty
F
4

i also have problem with yours sample, so i check sources and looks like u use different approach then is in sample, don't know why.

so i change and looks it works.

    <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

and import

Imports System.Runtime.InteropServices

i Have use dll from Download libwebp-0.6.0.zip from Thise instructions 'libwebp-0.6.0.zip\x64\bin' and it works.

When i try attache your dll from Download the compiled and zipped libwebp.dll here. This is the image file I'm using:

got exactly this same exception, looks like is not 64

for image i'm not sure, probaly u need reverse it

            '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")
Fraktur answered 2/5, 2018 at 9:56 Comment(2)
Thanks, the 0.6.0 dll does seem to help get passed the first error. You're saving source variable but it would need to save webp_data variable, how can I do so? And are you able to compile a 1.0.0 libwebp.dll for x64? I'd rather not use a 0.6.0 beta version and I don't know why it's not compiling correctly.Canty
Hi! Thank you once again for your help on this. I'm now getting the error There is insufficient system memory in resource pool 'internal' to run this query., I assume it's because I'm not clearing the memory. I see the WebPFree method in your code is empty, do you know what I should enter in there to clear the memory?Canty
H
5

How can I encode the image and save the encoded image to disk in WebP format?

After the conversion process, you need to marshall unmanaged memory so you can use the data in managed code.

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

BTW The command nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output ARCH=x64 you say you used is OK. I also could compile the library (version 1.0.0) with that command too. However I'm 100% positive that zipped libwebp.dll here is a 32-bit one, not 64-bit.

Make sure that you start the right environment to produce 64-bit binaries.

Heartworm answered 7/5, 2018 at 2:8 Comment(6)
Ok...this seems to save the webp image! Last step then: Which environment did you start to create a 64bit binary? I tried x64 Native Tools Command Prompt for Visual Studio 2017, I also tried my regular Windows command prompt which is running in 64bit mode and I tried Windows Powershell. None of these work for me.Canty
@Flo The same environment and the same commad with you. Here's the output directory screenshot with a dumpbin output: img.imgur.com/5BXzyuN.pngHeartworm
Ok...this drives me mad...could you share the compiled 64bit dll you have with me somewhere? I can then close this thread and assign the bounty and then figure out why it's not working on my machine....thank you in advance!Canty
Hmmm...I wanted to share the bounty between you and the other poster, but this is not possible on SO. Since the other poster was first and has provided the key part, the encoding to webp which was failing, I'm going to award him the bounty and start another bounty for you to award you 50 points...hope you understand :-)Canty
@Flo It's OK but an additional bounty for me is not necessary at all. Thank you.Heartworm
D'oh...turns out an additional bounty has be higher than what it was in the first place...cool that you're ok with it, thanks for your help! :-)Canty
F
4

i also have problem with yours sample, so i check sources and looks like u use different approach then is in sample, don't know why.

so i change and looks it works.

    <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

and import

Imports System.Runtime.InteropServices

i Have use dll from Download libwebp-0.6.0.zip from Thise instructions 'libwebp-0.6.0.zip\x64\bin' and it works.

When i try attache your dll from Download the compiled and zipped libwebp.dll here. This is the image file I'm using:

got exactly this same exception, looks like is not 64

for image i'm not sure, probaly u need reverse it

            '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")
Fraktur answered 2/5, 2018 at 9:56 Comment(2)
Thanks, the 0.6.0 dll does seem to help get passed the first error. You're saving source variable but it would need to save webp_data variable, how can I do so? And are you able to compile a 1.0.0 libwebp.dll for x64? I'd rather not use a 0.6.0 beta version and I don't know why it's not compiling correctly.Canty
Hi! Thank you once again for your help on this. I'm now getting the error There is insufficient system memory in resource pool 'internal' to run this query., I assume it's because I'm not clearing the memory. I see the WebPFree method in your code is empty, do you know what I should enter in there to clear the memory?Canty

© 2022 - 2024 — McMap. All rights reserved.