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

Adam
  • 6,041
  • 36
  • 120
  • 208
  • 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`. – Dai Apr 30 '18 at 15:53
  • It's possible it's the other way around: that IIS is running as 32-bit and it cannot load your 64-bit DLL. – Dai Apr 30 '18 at 18:54
  • 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... – Adam Apr 30 '18 at 18:58

2 Answers2

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.

Kul-Tigin
  • 16,728
  • 1
  • 35
  • 64
  • 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. – Adam May 07 '18 at 10:06
  • @Flo The same environment and the same commad with you. Here's the output directory screenshot with a [dumpbin](https://learn.microsoft.com/en-us/cpp/build/reference/dumpbin-reference) output: https://img.imgur.com/5BXzyuN.png – Kul-Tigin May 07 '18 at 14:33
  • 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! – Adam May 07 '18 at 15:07
  • 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 :-) – Adam May 07 '18 at 20:25
  • 2
    @Flo It's OK but an additional bounty for me is not necessary at all. Thank you. – Kul-Tigin May 07 '18 at 20:29
  • 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! :-) – Adam May 07 '18 at 20:30
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")
  • 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. – Adam May 02 '18 at 17:53
  • 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? – Adam May 18 '18 at 12:39