#include <wx/wxprec.h>
#include <wx/wx.h>
#include "../include/wxdragon.h"
#include <wx/image.h>
#include <wx/bitmap.h>
#include <cstdlib>
#include <cstring>
WXD_EXPORTED wxd_Bitmap_t*
wxd_Bitmap_CreateFromRGBA(const unsigned char* data, int width, int height)
{
if (!data || width <= 0 || height <= 0) {
return nullptr;
}
size_t num_pixels = static_cast<size_t>(width) * static_cast<size_t>(height);
size_t rgb_data_size = num_pixels * 3;
unsigned char* rgb_data = static_cast<unsigned char*>(malloc(rgb_data_size));
if (!rgb_data) {
WXD_LOG_ERROR("Failed to allocate memory for bitmap RGB data.");
return nullptr;
}
size_t alpha_data_size = num_pixels; unsigned char* alpha_data = static_cast<unsigned char*>(malloc(alpha_data_size));
if (!alpha_data) {
WXD_LOG_ERROR("Failed to allocate memory for bitmap Alpha data.");
free(rgb_data); return nullptr;
}
for (size_t i = 0; i < num_pixels; ++i) {
rgb_data[i * 3 + 0] = data[i * 4 + 0]; rgb_data[i * 3 + 1] = data[i * 4 + 1]; rgb_data[i * 3 + 2] = data[i * 4 + 2]; alpha_data[i] = data[i * 4 + 3]; }
wxImage image(width, height, rgb_data, alpha_data);
if (!image.IsOk()) {
WXD_LOG_ERROR("Failed to create wxImage from RGBA data.");
return nullptr;
}
wxBitmap* bitmap = new (std::nothrow) wxBitmap(image, -1);
if (!bitmap || !bitmap->IsOk()) {
WXD_LOG_ERROR("Failed to create wxBitmap from wxImage.");
delete bitmap; return nullptr;
}
return reinterpret_cast<wxd_Bitmap_t*>(bitmap);
}
WXD_EXPORTED void
wxd_Bitmap_Destroy(wxd_Bitmap_t* bitmap)
{
wxBitmap* bmp = reinterpret_cast<wxBitmap*>(bitmap);
if (!bmp)
return;
if (bmp == &wxNullBitmap)
return;
delete bmp;
}
WXD_EXPORTED int
wxd_Bitmap_GetWidth(const wxd_Bitmap_t* bitmap)
{
const wxBitmap* bmp = reinterpret_cast<const wxBitmap*>(bitmap);
if (!bmp || !bmp->IsOk())
return 0;
return bmp->GetWidth();
}
WXD_EXPORTED int
wxd_Bitmap_GetHeight(const wxd_Bitmap_t* bitmap)
{
const wxBitmap* bmp = reinterpret_cast<const wxBitmap*>(bitmap);
if (!bmp || !bmp->IsOk())
return 0;
return bmp->GetHeight();
}
WXD_EXPORTED bool
wxd_Bitmap_IsOk(const wxd_Bitmap_t* bitmap)
{
const wxBitmap* bmp = reinterpret_cast<const wxBitmap*>(bitmap);
if (!bmp)
return false;
return bmp->IsOk();
}
WXD_EXPORTED wxd_Bitmap_t*
wxd_Bitmap_Clone(const wxd_Bitmap_t* bitmap)
{
if (!bitmap) {
return nullptr;
}
const wxBitmap* original_bmp = reinterpret_cast<const wxBitmap*>(bitmap);
if (!original_bmp->IsOk()) {
return nullptr; }
wxBitmap* cloned_bmp = new (std::nothrow) wxBitmap(*original_bmp);
if (!cloned_bmp || !cloned_bmp->IsOk()) {
delete cloned_bmp; return nullptr;
}
return reinterpret_cast<wxd_Bitmap_t*>(cloned_bmp);
}
WXD_EXPORTED unsigned char*
wxd_Bitmap_GetRGBAData(const wxd_Bitmap_t* bitmap, size_t* width, size_t* height)
{
if (!bitmap) {
return nullptr;
}
const wxBitmap* bmp = reinterpret_cast<const wxBitmap*>(bitmap);
if (!bmp || !bmp->IsOk()) {
return nullptr;
}
wxImage image = bmp->ConvertToImage();
if (!image.IsOk()) {
return nullptr;
}
int w = image.GetWidth();
int h = image.GetHeight();
size_t num_pixels = static_cast<size_t>(w) * static_cast<size_t>(h);
size_t rgba_data_size = num_pixels * 4;
if (width) {
*width = static_cast<size_t>(w);
}
if (height) {
*height = static_cast<size_t>(h);
}
unsigned char* rgba_data = static_cast<unsigned char*>(malloc(rgba_data_size));
if (!rgba_data) {
return nullptr;
}
unsigned char* rgb_data = image.GetData();
unsigned char* alpha_data = image.GetAlpha();
for (size_t i = 0; i < num_pixels; ++i) {
rgba_data[i * 4 + 0] = rgb_data[i * 3 + 0]; rgba_data[i * 4 + 1] = rgb_data[i * 3 + 1]; rgba_data[i * 4 + 2] = rgb_data[i * 3 + 2];
if (alpha_data) {
rgba_data[i * 4 + 3] = alpha_data[i]; }
else {
rgba_data[i * 4 + 3] = 255; }
}
return rgba_data;
}
WXD_EXPORTED void
wxd_Bitmap_FreeRGBAData(unsigned char* data)
{
if (data) {
free(data);
}
}
WXD_EXPORTED const wxd_Bitmap_t*
wxd_Bitmap_GetNull(void)
{
return reinterpret_cast<const wxd_Bitmap_t*>(&wxNullBitmap);
}