#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "pngdll.h"
// Helper: get HMODULE of this DLL (works even if not linked via import lib)
static HMODULE self_module(void) {
HMODULE hm = NULL;
if (GetModuleHandleExA(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&self_module, &hm)) {
return hm;
}
return NULL;
}
// Load raw bytes from a resource
static gboolean load_resource_bytes(const char *name,
const char *type,
const void **data,
DWORD *size) {
HMODULE mod = self_module();
if (!mod) return FALSE;
HRSRC r = FindResourceA(mod, name, type);
if (!r) return FALSE;
*size = SizeofResource(mod, r);
if (*size == 0) return FALSE;
HGLOBAL h = LoadResource(mod, r);
if (!h) return FALSE;
*data = LockResource(h);
return (*data != NULL);
}
// Exported function: load PNG from resources into a GdkPixbuf
__declspec(dllexport)
GdkPixbuf* pngdll_load_pixbuf(const char *name, int width, int height) {
const void *data = NULL;
DWORD size = 0;
if (!load_resource_bytes(name, "PNG", &data, &size)) {
g_warning("pngdll: could not load resource '%s'", name);
return NULL;
}
// Create pixbuf loader
GError *error = NULL;
GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_type("png", &error);
if (!loader) {
g_warning("pngdll: gdk_pixbuf_loader_new_with_type failed: %s",
error ? error->message : "unknown error");
if (error) g_error_free(error);
return NULL;
}
// Feed resource data into loader
if (!gdk_pixbuf_loader_write(loader, (const guchar*)data, size, &error)) {
g_warning("pngdll: gdk_pixbuf_loader_write failed: %s",
error ? error->message : "unknown error");
if (error) g_error_free(error);
g_object_unref(loader);
return NULL;
}
gdk_pixbuf_loader_close(loader, NULL);
// Extract pixbuf
GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
if (!pixbuf) {
g_warning("pngdll: no pixbuf from loader");
g_object_unref(loader);
return NULL;
}
// Increase refcount since loader owns one
g_object_ref(pixbuf);
g_object_unref(loader);
// Scale if requested
if (width > 0 && height > 0) {
GdkPixbuf *scaled = gdk_pixbuf_scale_simple(pixbuf,
width,
height,
GDK_INTERP_BILINEAR);
g_object_unref(pixbuf);
pixbuf = scaled;
}
return pixbuf;
}