Skip to content

Commit

Permalink
* Force alpha to 255 when pasting copied images.
Browse files Browse the repository at this point in the history
Fixes #13. (ish)

* Add USE_DEBUG_PRINTS to allow debug prints to show on release mode.
  • Loading branch information
iProgramMC committed May 11, 2024
1 parent 5dbe15d commit eba49fc
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/discord/Frontend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class Frontend
virtual std::string GetFormatTimeShorterText() = 0;

// Debugging
#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS
virtual void DebugPrint(const char* fmt, va_list vl) = 0;
#endif
};
Expand Down
2 changes: 1 addition & 1 deletion src/discord/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ std::string GetAppVersionString()
return "V1.01";
}

#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS
void DbgPrintF(const char* fmt, ...)
{
va_list vl;
Expand Down
6 changes: 5 additions & 1 deletion src/discord/Util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include <nlohmann/json.h>
#include "Snowflake.hpp"

#ifdef _DEBUG
#define USE_DEBUG_PRINTS
#endif

std::string GetBasePath();
std::string GetCachePath();
void SetBasePath(const std::string& appDataPath);
Expand Down Expand Up @@ -40,7 +44,7 @@ float CompareFuzzy(const std::string& item, const char* query); // returns a "cl
float GetAppVersion();
std::string GetAppVersionString();

#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS
void DbgPrintF(const char* fmt, ...);
#else
#define DbgPrintF(...)
Expand Down
2 changes: 1 addition & 1 deletion src/windows/Frontend_Win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void Frontend_Win32::GetIdentifyProperties(nlohmann::json& j)
j["system_locale"] = "en-US";
}

#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS

void DbgPrintWV(const char* fmt, va_list vl)
{
Expand Down
2 changes: 1 addition & 1 deletion src/windows/Frontend_Win32.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Frontend_Win32 : public Frontend
std::string GetFormatTimeShortText() override;
std::string GetFormatTimeShorterText() override;

#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS
void DebugPrint(const char* fmt, va_list vl) override;
#endif
};
11 changes: 8 additions & 3 deletions src/windows/ImageLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ static void ConvertToPNGWriteFunc(void* context, void* data, int size)
memcpy(vec->data() + old_size, data, size);
}

bool ImageLoader::ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int width, int height, int widthBytes, int bpp)
bool ImageLoader::ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int width, int height, int widthBytes, int bpp, bool forceOpaque, bool flipVerticallyWhenSaving)
{
uint32_t* interm_data = new uint32_t[width * height];
uint8_t* bits_b = (uint8_t*) pBits;
uint32_t auxBits = 0;
if (forceOpaque)
auxBits = 255U << 24;

switch (bpp) {
case 32: {
Expand All @@ -175,7 +178,7 @@ bool ImageLoader::ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int w
uint8_t tmp = u.b[0];
u.b[0] = u.b[2];
u.b[2] = tmp;
*(write_ptr++) = u.x;
*(write_ptr++) = u.x | auxBits;
}
}
break;
Expand All @@ -186,7 +189,7 @@ bool ImageLoader::ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int w
for (int y = 0; y < height; y++) {
uint8_t* read_ptr = (uint8_t*)(bits_b + widthBytes * y);
for (int x = 0; x < width; x++) {
uint32_t rd = 255 << 24; // full alpha
uint32_t rd = 255U << 24; // full alpha
rd |= read_ptr[2];
rd |= read_ptr[1] << 8;
rd |= read_ptr[0] << 16;
Expand All @@ -203,6 +206,8 @@ bool ImageLoader::ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int w
return false;
}

stbi_flip_vertically_on_write(flipVerticallyWhenSaving);

if (!stbi_write_png_to_func(ConvertToPNGWriteFunc, (void*) outData, width, height, 4, (const void*) interm_data, width * sizeof(uint32_t))) {
delete[] interm_data;
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/windows/ImageLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ class ImageLoader
{
public:
static HBITMAP ConvertToBitmap(const uint8_t* pData, size_t size, int width = 0, int height = 0);
static bool ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int width, int height, int widthBytes, int bpp);
static bool ConvertToPNG(std::vector<uint8_t>* outData, void* pBits, int width, int height, int widthBytes, int bpp, bool forceOpaque, bool flipVerticallyWhenSaving);
};

83 changes: 48 additions & 35 deletions src/windows/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,22 +432,55 @@ BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
HDC hdc = NULL;
BYTE* pBytes = nullptr;
LPTSTR fileName = nullptr;
BITMAP bm;
BITMAPINFO bmi;
std::vector<uint8_t> data;
bool isClipboardClosed = false;
bool hadToUseLegacyBitmap = false;
int width = 0, height = 0, stride = 0, bpp = 0;

hbm = (HBITMAP) GetClipboardData (CF_BITMAP);
if (!hbm)
HANDLE hbmi = GetClipboardData(CF_DIB);
if (hbmi)
{
CloseClipboard();
DbgPrintW("Using CF_DIB to fetch image from clipboard");
PBITMAPINFO bmi = (PBITMAPINFO) GlobalLock(hbmi);

// No bitmap, forward to the edit control if selected
HWND hFocus = GetFocus();
if (hFocus == g_pMessageEditor->m_edit_hwnd)
SendMessage(hFocus, WM_PASTE, 0, 0);
width = bmi->bmiHeader.biWidth;
height = bmi->bmiHeader.biHeight;
bpp = bmi->bmiHeader.biBitCount;
stride = ((((width * bpp) + 31) & ~31) >> 3);

return FALSE;
int sz = stride * height;
pBytes = new BYTE[sz];
memcpy(pBytes, bmi + 1, sz);

GlobalUnlock(hbmi);
}
else
{
// try legacy CF_BITMAP
DbgPrintW("Using legacy CF_BITMAP");
HBITMAP hbm = (HBITMAP) GetClipboardData(CF_BITMAP);
hadToUseLegacyBitmap = true;

if (!hbm)
{
CloseClipboard();

// No bitmap, forward to the edit control if selected
HWND hFocus = GetFocus();
if (hFocus == g_pMessageEditor->m_edit_hwnd)
SendMessage(hFocus, WM_PASTE, 0, 0);

return FALSE;
}

HDC hdc = GetDC(hWnd);
bool res = GetDataFromBitmap(hdc, hbm, pBytes, width, height, bpp);
ReleaseDC(hWnd, hdc);

if (!res)
goto _fail;

stride = ((((width * bpp) + 31) & ~31) >> 3);
}

Channel* pChan = GetDiscordInstance()->GetCurrentChannel();
Expand All @@ -462,32 +495,12 @@ BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
goto _fail;
}

// Man what the hell
hdc = GetDC(hWnd);

ZeroMemory(&bm, sizeof bm);
if (!GetObject(hbm, sizeof bm, &bm)) {
DbgPrintW("Cannot obtain pointer to bitmap!");
goto _fail;
}

ZeroMemory(&bmi, sizeof bmi);
bmi.bmiHeader.biSize = sizeof bmi.bmiHeader;
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biHeight = -bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bm.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;

pBytes = new BYTE[bm.bmWidth * bm.bmHeight * (bm.bmBitsPixel / 8)];

if (!GetDIBits(hdc, hbm, 0, bm.bmHeight, pBytes, &bmi, DIB_RGB_COLORS)) {
DbgPrintW("Error, can't get DI bits for bitmap!");
goto _fail;
}
// TODO: Don't always force alpha when pasting from CF_DIB or CF_BITMAP.
// I know this sucks, but I've tried a lot of things...

if (!ImageLoader::ConvertToPNG(&data, pBytes, bm.bmWidth, bm.bmHeight, bm.bmWidth * sizeof(uint32_t), 32)) {
// have to force alpha always
// have to flip vertically if !hadToUseLegacyBitmap
if (!ImageLoader::ConvertToPNG(&data, pBytes, width, height, stride, 32, true, !hadToUseLegacyBitmap)) {
DbgPrintW("Cannot convert to PNG!");
goto _fail;
}
Expand Down
36 changes: 36 additions & 0 deletions src/windows/WinUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,3 +841,39 @@ void DrawErrorBox(HDC hdc, RECT rect)
int y = rect.top + (rect.bottom - rect.top - smcxsmicon) / 2;
DrawIconEx(hdc, x, y, g_ImgErrorIcon, smcxsmicon, smcxsmicon, 0, NULL, DI_COMPAT | DI_NORMAL);
}

bool GetDataFromBitmap(HDC hdc, HBITMAP hbm, BYTE*& pBytes, int& width, int& height, int& bpp)
{
// Man what the hell
BITMAP bm;
BITMAPINFO bmi;

ZeroMemory(&bm, sizeof bm);
if (!GetObject(hbm, sizeof bm, &bm)) {
DbgPrintW("Cannot obtain pointer to bitmap!");
return false;
}

width = bm.bmWidth;
height = bm.bmHeight;
bpp = bm.bmBitsPixel;

ZeroMemory(&bmi, sizeof bmi);
bmi.bmiHeader.biSize = sizeof bmi.bmiHeader;
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biHeight = -bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bm.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;

pBytes = new BYTE[bm.bmWidth * bm.bmHeight * (bm.bmBitsPixel / 8)];

if (!GetDIBits(hdc, hbm, 0, bm.bmHeight, pBytes, &bmi, DIB_RGB_COLORS)) {
DbgPrintW("Error, can't get DI bits for bitmap!");
delete[] pBytes;
return false;
}

return true;
}
3 changes: 2 additions & 1 deletion src/windows/WinUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ void DrawMentionStatus(HDC hdc, int x, int y, int mentionCount);
void DrawActivityStatus(HDC hdc, int x, int y, eActiveStatus status);
void DrawLoadingBox(HDC hdc, RECT rect);
void DrawErrorBox(HDC hdc, RECT rect);
bool GetDataFromBitmap(HDC hdc, HBITMAP hbm, BYTE*& pBytes, int& width, int& height, int& bpp);

#ifdef _DEBUG
#ifdef USE_DEBUG_PRINTS
void DbgPrintW(const char* fmt, ...);
#else
#define DbgPrintW(...)
Expand Down

0 comments on commit eba49fc

Please sign in to comment.