1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| #include <Windows.h> #include <stdio.h> #include <opencv2/opencv.hpp> #include <opencv2/lib.h>
#include <openssl/evp.h> #include <openssl/bio.h> #include <openssl/buffer.h>
static std::string base64_encode(const std::string &input) { BIO *bio, *b64; BUF_MEM *bufferPtr;
b64 = BIO_new(BIO_f_base64()); bio = BIO_new(BIO_s_mem()); bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
BIO_write(bio, input.data(), input.size()); BIO_flush(bio); BIO_get_mem_ptr(bio, &bufferPtr); BIO_set_close(bio, BIO_NOCLOSE);
std::string output(bufferPtr->data, bufferPtr->length);
BIO_free_all(bio); return output; }
static std::string base64_decode(const std::string &input) { BIO *bio, *b64; char *buffer = (char *) malloc(input.size()); memset(buffer, 0, input.size());
b64 = BIO_new(BIO_f_base64()); bio = BIO_new_mem_buf(input.data(), input.size()); bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
int decoded_size = BIO_read(bio, buffer, input.size()); std::string output(buffer, decoded_size);
BIO_free_all(bio); free(buffer);
return output; }
INT GetPixelDataOffsetForPackedDIB(const BITMAPINFOHEADER *BitmapInfoHeader) { INT OffsetExtra = 0; if (BitmapInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) { if (BitmapInfoHeader->biBitCount > 8) { if (BitmapInfoHeader->biCompression == BI_BITFIELDS) { OffsetExtra += 3 * sizeof(RGBQUAD); } else if (BitmapInfoHeader->biCompression == 6) { OffsetExtra += 4 * sizeof(RGBQUAD); } } } if (BitmapInfoHeader->biClrUsed > 0) { OffsetExtra += BitmapInfoHeader->biClrUsed * sizeof(RGBQUAD); } else { if (BitmapInfoHeader->biBitCount <= 8) { OffsetExtra += sizeof(RGBQUAD) << BitmapInfoHeader->biBitCount; } } return BitmapInfoHeader->biSize + OffsetExtra; }
bool GetBitmapDataFromPackedDIB(const HGLOBAL ClipboardDataHandle, std::vector<uchar> &bmpData) { const auto bitmapInfoHeader = static_cast<BITMAPINFOHEADER *>(GlobalLock(ClipboardDataHandle)); if (!bitmapInfoHeader) { CloseClipboard(); return false; } const SIZE_T clipboardDataSize = GlobalSize(ClipboardDataHandle); const INT pixelDataOffset = GetPixelDataOffsetForPackedDIB(bitmapInfoHeader); const size_t totalBitmapFileSize = sizeof(BITMAPFILEHEADER) + clipboardDataSize; BITMAPFILEHEADER BitmapFileHeader{}; BitmapFileHeader.bfType = 0x4D42; BitmapFileHeader.bfSize = static_cast<DWORD>(totalBitmapFileSize); BitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + pixelDataOffset; bmpData.clear(); bmpData.resize(totalBitmapFileSize); memcpy(bmpData.data(), &BitmapFileHeader, sizeof(BITMAPFILEHEADER)); memcpy(bmpData.data() + sizeof(BITMAPFILEHEADER), bitmapInfoHeader, clipboardDataSize);
GlobalUnlock(ClipboardDataHandle); return true; }
bool ConvertBmpDataToPng(const std::vector<uchar> &bmpData, std::vector<uchar> &pngData, int compression = 3, int flags = cv::IMREAD_COLOR) { const auto &bmp = cv::imdecode(bmpData, flags); if (bmp.empty()) { return false; } std::vector<int> compressionParams; compressionParams.push_back(cv::IMWRITE_PNG_COMPRESSION); compressionParams.push_back(compression);
pngData.clear(); if (!cv::imencode(".png", bmp, pngData, compressionParams)) { return false; } return true; }
int wmain(int argc, wchar_t *argv[]) { if (!OpenClipboard(NULL)) { return 1; } HGLOBAL ClipboardDataHandle = GetClipboardData(CF_DIB); if (!ClipboardDataHandle) { CloseClipboard(); return 0; } std::vector<uchar> bmpData{}; if (!GetBitmapDataFromPackedDIB(ClipboardDataHandle, bmpData)) { CloseClipboard(); return 0; } GlobalUnlock(ClipboardDataHandle); CloseClipboard();
std::vector<uchar> pngData; if (!ConvertBmpDataToPng(bmpData, pngData)) { return 0; } auto imgBase64 = base64_encode(std::string(pngData.begin(), pngData.end())); std::cout << "imgBase64: " << imgBase64 << std::endl; return 0; }
|