News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

WebP test libwebp.dll

Started by TimoVJL, October 14, 2022, 05:23:54 PM

Previous topic - Next topic

jj2007

Quote from: Biterider on October 15, 2022, 10:53:14 PM
The DLLs are those posted by TimoVJL.

https://www.dllme.com/dll/files/libwebp-7_dll.html has only 64-bit versions :sad:

And your *.lib files will work only if the dll is present, too.

TimoVJL

@Bitrider WebP_Demo.exepFile Data Description Value
00005460 8000000000000023 Ordinal 0023
00005468 8000000000000020 Ordinal 0020
00005470 800000000000000D Ordinal 000D
00005478 0000000000000000 End of Imports libwebp.dll

I still hunt newer dlls, but they are not in 1.2.4 package
May the source be with you

Biterider

Hi JJ
Quote from: jj2007 on October 15, 2022, 10:58:46 PM
And your *.lib files will work only if the dll is present, too.
The libs are import libraries, they don't contain any code, they only get access to the DLL procedures (but I'm sure you know that).

For everything to work properly we need to find the latest repo and fetch all files from there (single source of truth)  :biggrin:

Biterider

jj2007

Quote from: Biterider on October 15, 2022, 11:27:53 PMThe libs are import libraries, they don't contain any code, they only get access to the DLL procedures (but I'm sure you know that).

That's precisely why I am asking for the DLL :biggrin:

Unfortunately, I can't build it myself, since my C/C++ implementation suffers from a mysterious Micros*t bug.

Btw in my 64-bit implementation, I don't use any import libraries; they are a waste of space.

Biterider

Hi JJ

Quote from: jj2007 on October 16, 2022, 12:35:39 AM
... they are a waste of space.

I'm not sure what you mean, what space are you referring to?
AFAIK, import libs are only used by the linker to resolve references.  :rolleyes:

Biterider

jj2007

Hi Biterider,

What I mean is you don't need them at all:

jinvoke CreateWindowEx, WS_EX_CLIENTEDGE, Chr$("RichEdit20A"), NULL, reStyle, 0, 0, 1, 1, hWnd, ID_EDIT, wcx.hInstance, NULL

Dynamic loading, no import lib :cool:

Biterider

Hi JJ
I see, you are resolving at runtime, probably using a LoadLibrary / GetProcAddress combination and bypassing the import table.  :rolleyes:
At this point I would prefer to use the standard toolchain so anyone can use the DLL.

Biterider

TimoVJL

Quote from: jj2007 on October 15, 2022, 10:19:10 PM
include \masm32\include\masm32rt.inc
includelib BiteRider\libwebp.lib
.data?
wpWidth   dd ?
wpHeight  dd ?
.code
start:
  WebPGetInfo PROTO :DWORD, :DWORD, :DWORD, :DWORD
  invoke WebPGetInfo, 123, 123, addr wpWidth, addr wpHeight
end start


POLINK: error: Unresolved external symbol '_WebPGetInfo@16'
That library uses CDECL convention.
May the source be with you

jj2007

Quote from: TimoVJL on October 16, 2022, 06:56:33 AMThat library uses CDECL convention.

Thanks, Timo - this works:

WebPGetInfo PROTO C :DWORD, :DWORD, :DWORD, :DWORD

Quote from: Biterider on October 16, 2022, 02:19:48 AM
I see, you are resolving at runtime, probably using a LoadLibrary / GetProcAddress combination and bypassing the import table.  :rolleyes:

Hi Biterider,

Yes indeed. It has the additional advantage that you can give a non-cryptic user-friendly error message if LoadLibrary and/or GetProcAddress fail.

Biterider

Thanks TimoVJL
Quote from: TimoVJL on October 16, 2022, 06:56:33 AM
That library uses CDECL convention.
That explains it. It's kinda obvious...  :rolleyes:

Biterider


Vortex

Hi Timo,

Attached is the include file defining the function prototypes of libwebp.dll 32-bit

Biterider


TimoVJL

#27
x64 dll 1.0.2.1
https://github.com/JosePineiro/WebP-wrapper/tree/master/WebPTest

for Pelles C users:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>
#include <stdio.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "libwebp.lib")
#pragma comment(lib, "msvcrt.lib")

int __cdecl WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height);
uint8_t* __cdecl WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride);

void __cdecl mainCRTStartup(void)
{
HANDLE hFile;
hFile = CreateFile(TEXT("1.sm.webp"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD nSize = GetFileSize(hFile, NULL);
BYTE *pData = HeapAlloc(GetProcessHeap(), 0, nSize);
if (pData) {
DWORD nRead;
if (ReadFile(hFile, pData, nSize, &nRead, NULL))
{
CloseHandle(hFile);
int nWidth, nHeight;
TCHAR szTmp[80];
if (WebPGetInfo(pData, nSize, &nWidth, &nHeight)) {
TCHAR szTmp[80];
wsprintf(szTmp, TEXT("width: %d Heigth: %d"), nWidth, nHeight);
//MessageBox(0, szTmp, TEXT("WebP test"), MB_OK);
puts(szTmp);
BITMAPINFO bmih;
memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
bmih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmih.bmiHeader.biWidth = nWidth;
bmih.bmiHeader.biHeight = -nHeight;
bmih.bmiHeader.biPlanes = 1;
bmih.bmiHeader.biBitCount = 32;
bmih.bmiHeader.biCompression = BI_RGB;
bmih.bmiHeader.biSizeImage = nWidth * nHeight * sizeof(RGBQUAD);
//bmih.bmiHeader.biXPelsPerMeter = 0;
//bmih.bmiHeader.biYPelsPerMeter = 0;
//bmih.bmiHeader.biClrUsed = 0;
//bmih.bmiHeader.biClrImportant = 0;
BYTE *pPixels;
HBITMAP hBitmap = CreateDIBSection(0, &bmih, DIB_RGB_COLORS, (void*)&pPixels, NULL, 0);
int iStride = ((((bmih.bmiHeader.biWidth * bmih.bmiHeader.biBitCount) + 31) & ~31) >> 3);
WebPDecodeBGRAInto(pData, nSize, pPixels, bmih.bmiHeader.biSizeImage, iStride);

BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4D42;
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmih.bmiHeader.biSizeImage;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;

hFile = CreateFile(TEXT("1.sm.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
DWORD dwWrite;
WriteFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwWrite, NULL);
WriteFile(hFile, &bmih, sizeof(BITMAPINFOHEADER), &dwWrite, NULL);
WriteFile(hFile, pPixels, bmih.bmiHeader.biSizeImage, &dwWrite, NULL);
CloseHandle(hFile);

}
HeapFree(GetProcessHeap(), 0, pData);
}
}

}
ExitProcess(0);
}


A survey of the various ways of creating GDI bitmaps with predefined data Raymond Chen
May the source be with you

Biterider

Hi
I was able to successfully adjust the set of includes to fit 64 and 32 bit perfectly.  :cool:
This clean set of files is based on the latest available version (1.2.4) from Google and contains the complete prototype definitions, enumerations and structures.

In my case I switch back and forth from 32 to 64 bit during development. In order for my 64-bit operating system to pick up the correct DLL, I copied the 64-bit version to C:\WINDOWS\SYSTEM32 and the 32-bit version to C:\WINDOWS\SYSWOW64.

As a starting point for working with webp images, I wrote the following routines (UNICODE version):

; Procedure:  LoadWebPAsBmpW
; Purpose:    Load WebP encoded file and convert it to a bitmap.
; Arguments:  Arg1: -> WIDE file name.
; Return:     xax = Bitmap HANDLE or zero if failed.

LoadWebPAsBmpW proc pFileName:PSTRINGW
  local hBmp:HBITMAP, hFile:HANDLE, pData:POINTER, dDataSize:DWORD, dBytesRead:DWORD
  local dWidth:DWORD, dHeight:DWORD, dStride:DWORD, BmpInfo:BITMAPINFO, pPixels:POINTER

  mov hBmp, 0
  invoke CreateFileW, pFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0
  .if xax != INVALID_HANDLE_VALUE
    mov hFile, xax
    invoke GetFileSize, hFile, NULL
    .if eax != INVALID_FILE_SIZE
      mov dDataSize, eax
      MemAlloc dDataSize
      .if xax != 0
        mov pData, xax
        invoke ReadFile, hFile, pData, dDataSize, addr dBytesRead, NULL
        invoke WebPGetInfo, pData, dDataSize, addr dWidth, addr dHeight

        mov BmpInfo.BITMAPINFO.bmiHeader.biSize, sizeof BITMAPINFO
        mov BmpInfo.BITMAPINFO.bmiHeader.biPlanes, 1
        mov BmpInfo.BITMAPINFO.bmiHeader.biBitCount, 32
        mov BmpInfo.BITMAPINFO.bmiHeader.biCompression, BI_RGB
        m2m BmpInfo.bmiHeader.biWidth, dWidth, eax
        shl eax, $Log2(sizeof(RGBQUAD))
        mov dStride, eax
        mov ecx, dHeight
        mul ecx
        mov BmpInfo.BITMAPINFO.bmiHeader.biSizeImage, eax
        neg ecx                                 ;Top down scanline arrangement
        mov BmpInfo.bmiHeader.biHeight, ecx

        invoke CreateDIBSection, 0, addr BmpInfo, DIB_RGB_COLORS, addr pPixels, 0, 0
        .if xax != 0
          mov hBmp, xax
          invoke WebPDecodeBGRAInto, pData, dDataSize, pPixels, \
                                     BmpInfo.BITMAPINFO.bmiHeader.biSizeImage, dStride
        .endif
        MemFree pData
      .endif
    .endif
    invoke CloseHandle, hFile
  .endif
  mov xax, hBmp
  ret
LoadWebPAsBmpW endp



; Procedure:  SaveBmpAsWebPW
; Purpose:    Save a Bitmap (DDB or DIB) to as WebP encoded file.
; Arguments:  Arg1: Bitmap HANDLE.
;             Arg2: Quality factor (REAL4), min: 0.0, lossless: 100.0
;             Arg3: -> WIDE file name.
; Return:     eax = TRUE if succeeded, otherwise FALSE.

SaveBmpAsWebPW proc hBmp:HBITMAP, r4Quality:REAL4, pFileName:PSTRINGW
  local dSuccess:DWORD, BmpInfo:BITMAPINFO
  local hDC:HDC, hDesktop:HWND, Bmp:BITMAP, pPixels:POINTER, dStride:DWORD
  local hFile:HANDLE, pBuffer:POINTER, dBufferSize:DWORD, dBytesWritten:DWORD

  mov dSuccess, FALSE
  invoke GetObject, hBmp, sizeof Bmp, addr Bmp
  .if eax != 0
    mrm BmpInfo.bmiHeader.biWidth, Bmp.bmWidth, ecx
    shl ecx, $Log2(sizeof(RGBQUAD))
    mov dStride, ecx
    mov edx, Bmp.bmHeight
    mov eax, edx
    neg edx
    mov BmpInfo.bmiHeader.biHeight, edx
    mul ecx
    MemAlloc eax
    .if xax != NULL
      mov pPixels, xax
      mov hDesktop, $invoke(GetDesktopWindow)
      mov hDC, $invoke(GetDC, hDesktop)
      mov BmpInfo.bmiHeader.biSize, sizeof(BITMAPINFOHEADER)
      mov BmpInfo.bmiHeader.biPlanes, 1
      mov BmpInfo.bmiHeader.biBitCount, 32
      mov BmpInfo.bmiHeader.biCompression, BI_RGB
      invoke GetDIBits, hDC, hBmp, 0, Bmp.BITMAP.bmHeight, pPixels, addr BmpInfo, DIB_RGB_COLORS
      .if eax != 0
        invoke WebPEncodeBGRA, pPixels, Bmp.BITMAP.bmWidth, Bmp.BITMAP.bmHeight, dStride, \
                               r4Quality, addr pBuffer
        .if eax != 0
          mov dBufferSize, eax
          invoke CreateFileW, pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, \
                              FILE_ATTRIBUTE_ARCHIVE, 0
          .if xax != INVALID_HANDLE_VALUE
            mov hFile, xax
            invoke WriteFile, hFile, pBuffer, dBufferSize, addr dBytesWritten, NULL
            .if eax != FALSE
              mov dSuccess, TRUE
            .endif
            invoke CloseHandle, hFile
          .endif
          invoke WebPFree, pBuffer
        .endif
      .endif
      invoke ReleaseDC, hDesktop, hDC
    .endif
    MemFree pPixels
  .endif
  mov eax, dSuccess
  ret
SaveBmpAsWebPW endp


Biterider

TimoVJL

GDI+ soon support WebP format in Windows 10 / 11?
DEFINE_GUID(ImageFormatWEBP, 0xb96b3cb7,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);//---------------------------------------------------------------------------
// Image file format identifiers
//---------------------------------------------------------------------------

DEFINE_GUID(ImageFormatUndefined, 0xb96b3ca9,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatMemoryBMP, 0xb96b3caa,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatBMP, 0xb96b3cab,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatEMF, 0xb96b3cac,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatWMF, 0xb96b3cad,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatJPEG, 0xb96b3cae,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatPNG, 0xb96b3caf,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatGIF, 0xb96b3cb0,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatTIFF, 0xb96b3cb1,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatEXIF, 0xb96b3cb2,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatIcon, 0xb96b3cb5,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatHEIF, 0xb96b3cb6,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
DEFINE_GUID(ImageFormatWEBP, 0xb96b3cb7,0x0728,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);
May the source be with you