Skip to content

Instantly share code, notes, and snippets.

@alf-p-steinbach
Last active January 19, 2020 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alf-p-steinbach/dd46eff089924deefcacfedc0f1a1c6c to your computer and use it in GitHub Desktop.
Save alf-p-steinbach/dd46eff089924deefcacfedc0f1a1c6c to your computer and use it in GitHub Desktop.
Gdi+ bitmap from base-64 encoded data
#pragma once
#include <string_view> // std::string_view
//---------------------------------------- Lenna image scaled down to 51x51:
namespace lenna {
using std::string_view;
const auto& data_literal = R"(
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
MTVpu7Zoq/7hVlPlTm+zZ6BtZ/ipZ6zHM9G7OzP8ZuVZlzPxGZW+b1bsmdX1AQT6
33z09yI22mpfj/eUcyNpx6GiU3DeKTiQFOyTsEcUxZTJ9DzV9iLFAqr0Qz/xRwPV
PIgRfUjX7BoFwH8quR3cCMW2wDCdgTiAbCtR0x0S/jQkfBBPeUbnjjH4k1z+MJP/
Kit5PS99ozxvs7poq+XxVnP1dmeDp6/VM9TuHunaGe/dmRpyTw+Pcfn7NsWuSVbs
h4qnqle7Gt/MDb5fHOktLqEeh/G8wKxj/tyT0Hhf+qzZ8jwx5kWy9XmSGVQPwzZB
0X1BAJn4MFMD7NU+wRWAinBsOxzTHRjaFxK2/yC6MyisM5AwiCNNkFgTNM4IS/jS
YV5x2jfyMjbL8zcel6xVFG5Ul2w3Vbk7G9x9rauNVduDHe6Rp1sjPdt9bQdm3qZd
M1eavz3UfjDVuzve/XZhtCMzm+4FAxoR56vJYGMa07LL9jLJ+jzBshJnAjXBsY1Q
zBAK89oh+ZSnfeuUVvsEVt4LaYJhWqDojgBsRwDuqMoySojoDAwfwPwfGVP0Qh81
r9G8cNheZSSvFWav5qWvlzzYLMvdqCzcqC1ff1K61ly93l6/1lzzsqVupblu50m+
p69+b6TdM9rpAQ7KcMeHpbECuZF5EsY4dl/gjXgcJluyWl+l2F8kxgBky3FmUB0U
Ww9B94aEvnGJj/Ki38ZKq31DqnxCmqGYZiiqHY7uRIf/WW1al7P6UWG96IgRMmdZ
pZ6SKp4b9MtG44s451pa4mZe2mZB+npu+mpO2lpp7vrjh6u1latVZc9LCp5XFW22
P9rpa/IMtbqH2j0jnbtDbS+Lsna76xQ3cCwvMPOYv/6n8Dk9UEfHV7Ik23NAtkQL
qAaMrvFHDaLxb12Sj3nR71zSaj90lQ+qEYJpgqBaoKhOPOnLE73HyJsikfpx1AWp
YpwrXlJHzinUi3rDK5vtpTNhIT593uF8mRz3KiNp7UHa6oOM51mZy9kP1h/l73RU
untqtnsa3AOtu6NP9yf7XpbnzzhixrIyyN8CuQrjeQe0c7VLNuuLZDtgsudJMcuJ
lhWArA4a2gALncTh38VJjvK17+OlQHcqvxvSAME0Q1Bt4OAOfMRfXa7X8fxXEtoE
lTPIEC3K5FN8ybREtajRj0jMNYTIYmzkoDGjVhhXL7JXUqMSAyTzyWlbTwp2e2q3
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)";
// 1 byte for zero-termination, 1 byte for initial newline => 2 byte adjustment.
constexpr auto data = string_view( data_literal + 1, sizeof( data_literal ) - 2 );
} // namespace lenna
// For C++17 and later. Link with "gdiplus", "shlwapi" and "crypt32".
#include <header-wrappers/winapi/gdiplus-h.hpp>
#include <header-wrappers/winapi/wincrypt-h.hpp> // CryptStringToBinaryA
#include <header-wrappers/winapi/shlwapi-h.hpp>
#include <stddef.h> // ptrdiff_t
#include <fstream> // std::ofstream
#include <iostream> // std::clog
#include <memory> // std::unique_ptr
#include <optional> // std::optional
#include <stdexcept> // std::(exception, runtime_error)
#include <string> // std::string
#include <string_view> // std::string_view
#include <type_traits> // std::(is_class_v, is_aggregate_v)
#include "lenna.hpp" // - 51x51 Lenna image, base-64 encoded, 7662 bytes decoded.
//---------------------------------------- Extending the core language & std library:
#define WITH( ... ) \
if( const auto& _ [[maybe_unused]] = __VA_ARGS__; true )
namespace cppx {
using std::runtime_error, std::string;
template< class T > constexpr bool has_constructor =
std::is_class_v<T> and not std::is_aggregate_v<T>;
template< class T > using Type_ = T;
using Byte = unsigned char;
using Size = ptrdiff_t;
auto hopefully( const bool expr ) -> bool { return expr; }
auto fail( const string& message ) -> bool { throw runtime_error( message ); }
} // namespace cppx
//---------------------------------------- Base64 decryption:
namespace base64 {
using std::optional, std::string;
using cppx::Size;
// Based on the Windows API's CryptStringToBinaryA, <url:
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptstringtobinarya>
// because "polfosol"'s function, <url:
// https://stackoverflow.com/a/37109258>, didn't work.
auto decode( const void* data, const Size len )
-> optional<string>
{
using R = optional<string>;
const DWORD flags = CRYPT_STRING_BASE64;
DWORD n_bytes = 0;
const bool found_n_bytes = !!CryptStringToBinaryA(
reinterpret_cast<const char*>( data ), // LPCSTR pszString,
len, // DWORD cchString,
flags, // DWORD dwFlags,
nullptr, // BYTE *pbBinary,
&n_bytes, // DWORD *pcbBinary,
nullptr, // DWORD *pdwSkip,
nullptr // DWORD *pdwFlags
);
if( not found_n_bytes ) {
return R();
} else if( n_bytes <= 1 ) {
return R( "" );
}
auto result = string( n_bytes, '\0' );
const bool success = !!CryptStringToBinaryA(
reinterpret_cast<const char*>( data ), // LPCSTR pszString,
len, // DWORD cchString,
flags, // DWORD dwFlags,
reinterpret_cast<BYTE*>( result.data() ), // BYTE *pbBinary,
&n_bytes, // DWORD *pcbBinary,
nullptr, // DWORD *pdwSkip,
nullptr // DWORD *pdwFlags
);
return (success? R( result ) : R());
}
} // namespace base64
//---------------------------------------- GDI+ wrapping:
namespace gdi_plusplus {
using std::to_string, std::unique_ptr;
using
cppx::Type_, cppx::has_constructor,
cppx::Size, cppx::Byte,
cppx::hopefully, cppx::fail;
namespace gp = Gdiplus; // Microsoft's GDI+ API.
// API function result type.
namespace status {
using Enum = gp::Status;
using gp::Ok; // Etc.
}
class Library_usage
{
ULONG_PTR m_token;
public:
Library_usage()
{
static_assert( has_constructor<gp::GdiplusStartupInput>, "!" );
gp::GdiplusStartupInput startup_input;
const status::Enum rc = gp::GdiplusStartup( &m_token, &startup_input, nullptr );
hopefully( rc == status::Ok )
or fail( "GdiplusStartup failed, code " + to_string( rc ) );
}
~Library_usage() { gp::GdiplusShutdown( m_token ); }
};
auto bitmap_from_bytes( const Type_<const void*> p_bytes, const Size len )
-> unique_ptr<gp::Bitmap>
{
using R = unique_ptr<gp::Bitmap>;
struct Stream
{
IStream* p;
Stream( const Type_<const void*> p_bytes, const Size len ):
p( SHCreateMemStream( reinterpret_cast<const Byte*>( p_bytes ), len ) )
{
hopefully( p != nullptr )
or fail( "SHCreateMemStream failed" );
}
~Stream() { p->Release(); }
};
Stream stream( p_bytes, len );
return R( gp::Bitmap::FromStream( stream.p ) );
}
auto size_of( const gp::Image& image )
-> gp::SizeF
{
gp::SizeF result;
const status::Enum result_code =
const_cast<gp::Image&>( image ).GetPhysicalDimension( &result );
hopefully( result_code == status::Ok )
or fail( "GdiPlus::Image::GetPhysicalDimension failed" );
return result;
}
} // namespace gdi_plusplus
//---------------------------------------- Demo app:
namespace app {
using std::ofstream, std::optional, std::string, std::unique_ptr, std::cout, std::endl;
using cppx::hopefully, cppx::fail;
void run()
{
namespace gp = Gdiplus;
namespace gpp = gdi_plusplus;
WITH( gpp::Library_usage() ) {
const optional<string> lenna_image_bytes = base64::decode(
&lenna::data[0], lenna::data.size()
);
hopefully( lenna_image_bytes.has_value() )
or fail( "base64::decode failed to decode lenna image data." );
#ifdef SAVE_RAW_PLEASE
{ // Save the raw image bytes.
ofstream f( "image.raw-bytes.jpg", ofstream::binary );
f.write( lenna_image_bytes->data(), lenna_image_bytes->size() );
}
#endif
unique_ptr<gp::Bitmap> lenna = gpp::bitmap_from_bytes(
lenna_image_bytes->data(), lenna_image_bytes->size()
);
const gp::SizeF size = gpp::size_of( *lenna );
cout << "GDI+ successfully constructed a "
<< size.Width << "x" << size.Height << " image."
<< endl;
}
}
} // namespace app
#include <stdlib.h> // EXIT_...
auto main()
-> int
{
using std::exception, std::clog, std::endl;
try {
app::run();
return EXIT_SUCCESS;
} catch( const exception& x ) {
clog << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment