fix bug where window can't load icon with ico(#192)
This commit is contained in:
parent
c8d0b2a621
commit
b1fe1ca412
@ -14,7 +14,7 @@ namespace nana{ namespace paint{
|
|||||||
{
|
{
|
||||||
image_impl_interface& operator=(const image_impl_interface& rhs);
|
image_impl_interface& operator=(const image_impl_interface& rhs);
|
||||||
public:
|
public:
|
||||||
typedef nana::paint::graphics& graph_reference;
|
using graph_reference = nana::paint::graphics&;
|
||||||
virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp
|
virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp
|
||||||
virtual bool open(const std::experimental::filesystem::path& file) = 0;
|
virtual bool open(const std::experimental::filesystem::path& file) = 0;
|
||||||
virtual bool open(const void* data, std::size_t bytes) = 0; // reads image from memory
|
virtual bool open(const void* data, std::size_t bytes) = 0; // reads image from memory
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#endif
|
#endif
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "../../paint/detail/image_ico.hpp"
|
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
#include <nana/system/platform.hpp>
|
#include <nana/system/platform.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,44 +1,299 @@
|
|||||||
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
||||||
#define NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
#define NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
||||||
|
|
||||||
#include <nana/filesystem/filesystem_ext.hpp>
|
#include "image_pixbuf.hpp"
|
||||||
#include <nana/paint/detail/image_impl_interface.hpp>
|
#include <fstream>
|
||||||
|
|
||||||
namespace nana{ namespace paint
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
class image_ico
|
|
||||||
:public image::image_impl_interface
|
|
||||||
{
|
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
struct handle_deleter
|
# include <windows.h>
|
||||||
{
|
|
||||||
void operator()(HICON* handle) const;
|
|
||||||
};//end struct handle_deleter
|
|
||||||
typedef std::shared_ptr<HICON> ptr_t;
|
|
||||||
#else
|
|
||||||
typedef std::shared_ptr<int*> ptr_t;
|
|
||||||
#endif
|
#endif
|
||||||
public:
|
|
||||||
image_ico(bool is_ico);
|
namespace nana {
|
||||||
|
namespace paint {
|
||||||
|
namespace detail {
|
||||||
|
// These next two structs represent how the icon information is stored
|
||||||
|
// in an ICO file.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t bWidth; // Width of the image
|
||||||
|
uint8_t bHeight; // Height of the image (times 2)
|
||||||
|
uint8_t bColorCount; // Number of colors in image (0 if >=8bpp)
|
||||||
|
uint8_t bReserved; // Reserved
|
||||||
|
uint16_t wPlanes; // Color Planes
|
||||||
|
uint16_t wBitCount; // Bits per pixel
|
||||||
|
uint32_t dwBytesInRes; // how many bytes in this resource?
|
||||||
|
uint32_t dwImageOffset; // where in the file is this image
|
||||||
|
} ICONDIRENTRY, *LPICONDIRENTRY;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t idReserved; // Reserved
|
||||||
|
uint16_t idType; // resource type (1 for icons)
|
||||||
|
uint16_t idCount; // how many images?
|
||||||
|
//ICONDIRENTRY idEntries[1]; // the entries for each image
|
||||||
|
} ICONDIR, *LPICONDIR;
|
||||||
|
|
||||||
|
// size - 40 bytes
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t biSize;
|
||||||
|
uint32_t biWidth;
|
||||||
|
uint32_t biHeight; // Icon Height (added height of XOR-Bitmap and AND-Bitmap)
|
||||||
|
uint16_t biPlanes;
|
||||||
|
uint16_t biBitCount;
|
||||||
|
uint32_t biCompression;
|
||||||
|
int32_t biSizeImage;
|
||||||
|
uint32_t biXPelsPerMeter;
|
||||||
|
uint32_t biYPelsPerMeter;
|
||||||
|
uint32_t biClrUsed;
|
||||||
|
uint32_t biClrImportant;
|
||||||
|
} s_BITMAPINFOHEADER, *s_PBITMAPINFOHEADER;
|
||||||
|
|
||||||
|
// 46 bytes
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s_BITMAPINFOHEADER icHeader; // DIB header
|
||||||
|
uint32_t icColors[1]; // Color table (short 4 bytes) //RGBQUAD
|
||||||
|
uint8_t icXOR[1]; // DIB bits for XOR mask
|
||||||
|
uint8_t icAND[1]; // DIB bits for AND mask
|
||||||
|
} ICONIMAGE, *LPICONIMAGE;
|
||||||
|
|
||||||
|
|
||||||
bool open(const std::experimental::filesystem::path& filename) override;
|
class image_ico
|
||||||
bool open(const void* data, std::size_t bytes) override;
|
: public basic_image_pixbuf
|
||||||
bool alpha_channel() const override;
|
{
|
||||||
bool empty() const override;
|
bool _m_read_ico(const void* data, std::size_t /*size*/)
|
||||||
void close() override;
|
{
|
||||||
nana::size size() const override;
|
auto width = 0;
|
||||||
virtual void paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override;
|
auto height = 0;
|
||||||
virtual void stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const override;
|
auto buffer = (unsigned char *)data;
|
||||||
const ptr_t & ptr() const;
|
auto icoDir = reinterpret_cast<LPICONDIR>(buffer);
|
||||||
private:
|
int iconsCount = icoDir->idCount;
|
||||||
const bool is_ico_;
|
if (icoDir->idReserved != 0 || icoDir->idType != 1 || iconsCount == 0 || iconsCount > 20)
|
||||||
nana::size size_;
|
return false;
|
||||||
ptr_t ptr_;
|
|
||||||
};//end class image_ico
|
auto cursor = buffer;
|
||||||
|
cursor += 6;
|
||||||
|
auto dirEntry = reinterpret_cast<ICONDIRENTRY*>(cursor);
|
||||||
|
auto maxSize = 0;
|
||||||
|
auto offset = 0;
|
||||||
|
auto maxBitCount = 0;
|
||||||
|
for (auto i = 0; i < iconsCount; i++, ++dirEntry)
|
||||||
|
{
|
||||||
|
int w = dirEntry->bWidth;
|
||||||
|
int h = dirEntry->bHeight;
|
||||||
|
int bitCount = dirEntry->wBitCount;
|
||||||
|
if (w * h > maxSize || bitCount > maxBitCount) // we choose icon with max resolution
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
offset = dirEntry->dwImageOffset;
|
||||||
|
maxSize = w * h;
|
||||||
|
maxBitCount = bitCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == 0) return false;
|
||||||
|
|
||||||
|
cursor = buffer;
|
||||||
|
cursor += offset;
|
||||||
|
auto icon = reinterpret_cast<ICONIMAGE*>(cursor);
|
||||||
|
auto realBitsCount = static_cast<int>(icon->icHeader.biBitCount);
|
||||||
|
auto hasAndMask = (realBitsCount < 32) && (height != static_cast<int>(icon->icHeader.biHeight));
|
||||||
|
cursor += 40;
|
||||||
|
pixbuf_.open(width, height);
|
||||||
|
|
||||||
|
// rgba + vertical swap
|
||||||
|
if (realBitsCount >= 32)
|
||||||
|
{
|
||||||
|
for (auto x = 0; x < width; ++x)
|
||||||
|
for (auto y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
pixbuf_.alpha_channel(true);
|
||||||
|
auto shift2 = 4 * (x + (height - y - 1) * width);
|
||||||
|
pixel_color_t image;
|
||||||
|
image.element.red = cursor[shift2 + 2];
|
||||||
|
image.element.green = cursor[shift2 + 1];
|
||||||
|
image.element.blue = cursor[shift2];
|
||||||
|
image.element.alpha_channel = cursor[shift2 + 3];
|
||||||
|
pixbuf_.pixel(x, y, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (realBitsCount == 24)
|
||||||
|
{
|
||||||
|
for (auto x = 0; x < width; x++)
|
||||||
|
for (auto y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
pixbuf_.alpha_channel(true);
|
||||||
|
auto shift2 = 3 * (x + (height - y - 1) * width);
|
||||||
|
pixel_color_t image;
|
||||||
|
image.element.red = cursor[shift2 + 2];
|
||||||
|
image.element.green = cursor[shift2 + 1];
|
||||||
|
image.element.blue = cursor[shift2];
|
||||||
|
image.element.alpha_channel = 255;
|
||||||
|
pixbuf_.pixel(x, y, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (realBitsCount == 8) /// 256 colors
|
||||||
|
{
|
||||||
|
// 256 color table
|
||||||
|
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
||||||
|
cursor += 256 * 4;
|
||||||
|
for (auto x = 0; x < width; x++)
|
||||||
|
for (auto y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
pixbuf_.alpha_channel(true);
|
||||||
|
|
||||||
|
auto shift2 = (x + (height - y - 1) * width);
|
||||||
|
auto index = 4 * cursor[shift2];
|
||||||
|
pixel_color_t image;
|
||||||
|
image.element.red = colors[index + 2];
|
||||||
|
image.element.green = colors[index + 1];
|
||||||
|
image.element.blue = colors[index];
|
||||||
|
image.element.alpha_channel = 255;
|
||||||
|
pixbuf_.pixel(x, y, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (realBitsCount == 4) /// 16 colors
|
||||||
|
{
|
||||||
|
// 16 color table
|
||||||
|
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
||||||
|
cursor += 16 * 4;
|
||||||
|
for (auto x = 0; x < width; x++)
|
||||||
|
for (auto y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
auto shift2 = (x + (height - y - 1) * width);
|
||||||
|
auto index = cursor[shift2 / 2];
|
||||||
|
if (shift2 % 2 == 0)
|
||||||
|
index = (index >> 4) & 0xF;
|
||||||
|
else
|
||||||
|
index = index & 0xF;
|
||||||
|
index *= 4;
|
||||||
|
pixbuf_.alpha_channel(true);
|
||||||
|
pixel_color_t image;
|
||||||
|
image.element.red = colors[index + 2];
|
||||||
|
image.element.green = colors[index + 1];
|
||||||
|
image.element.blue = colors[index];
|
||||||
|
image.element.alpha_channel = 255;
|
||||||
|
pixbuf_.pixel(x, y, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (realBitsCount == 1) /// 2 colors
|
||||||
|
{
|
||||||
|
// 2 color table
|
||||||
|
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
||||||
|
cursor += 2 * 4;
|
||||||
|
auto boundary = width; //!!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
|
||||||
|
while (boundary % 32 != 0) boundary++;
|
||||||
|
for (auto x = 0; x < width; x++)
|
||||||
|
for (auto y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
auto shift2 = (x + (height - y - 1) * boundary);
|
||||||
|
auto index = cursor[shift2 / 8];
|
||||||
|
|
||||||
|
// select 1 bit only
|
||||||
|
unsigned char bit = 7 - (x % 8);
|
||||||
|
index = (index >> bit) & 0x01;
|
||||||
|
index *= 4;
|
||||||
|
pixbuf_.alpha_channel(true);
|
||||||
|
pixel_color_t image;
|
||||||
|
image.element.red = colors[index + 2];
|
||||||
|
image.element.green = colors[index + 1];
|
||||||
|
image.element.blue = colors[index];
|
||||||
|
image.element.alpha_channel = 255;
|
||||||
|
pixbuf_.pixel(x, y, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read AND mask after base color data - 1 BIT MASK
|
||||||
|
if (hasAndMask)
|
||||||
|
{
|
||||||
|
auto boundary = width * realBitsCount; //!!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
|
||||||
|
while (boundary % 32 != 0) boundary++;
|
||||||
|
cursor += boundary * height / 8;
|
||||||
|
boundary = width;
|
||||||
|
while (boundary % 32 != 0) boundary++;
|
||||||
|
for (auto y = 0; y < height; y++)
|
||||||
|
for (auto x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
unsigned char bit = 7 - (x % 8);
|
||||||
|
auto shift2 = (x + (height - y - 1) * boundary) / 8;
|
||||||
|
auto mask = (0x01 & (static_cast<unsigned char>(cursor[shift2]) >> bit));
|
||||||
|
auto pc = pixbuf_.pixel(x, y);
|
||||||
|
auto alpha = pc.element.alpha_channel;
|
||||||
|
alpha *= 1 - mask;
|
||||||
|
pc.element.alpha_channel = alpha;
|
||||||
|
pixbuf_.pixel(x, y, pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
~image_ico()
|
||||||
|
{
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
if (native_handle_)
|
||||||
|
::DestroyIcon(reinterpret_cast<HICON>(native_handle_));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const std::experimental::filesystem::path& ico_file) override
|
||||||
|
{
|
||||||
|
std::ifstream file(ico_file.string(), std::ios::binary);
|
||||||
|
if (!file.is_open()) return false;
|
||||||
|
|
||||||
|
// allocates a buffer for the image
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
const auto bytes = static_cast<std::size_t>(file.tellg());
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
auto buffer = new char[bytes];
|
||||||
|
|
||||||
|
// read data from the file and set them in the buffer
|
||||||
|
file.read(buffer, bytes);
|
||||||
|
auto okret = _m_read_ico(buffer, bytes);
|
||||||
|
|
||||||
|
// delete buffer and return
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
if (okret)
|
||||||
|
path_ = ico_file;
|
||||||
|
|
||||||
|
return okret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const void* data, std::size_t bytes) override
|
||||||
|
{
|
||||||
|
if (_m_read_ico(data, bytes))
|
||||||
|
{
|
||||||
|
native_handle_ = ::CreateIconFromResourceEx(reinterpret_cast<PBYTE>(const_cast<void*>(data)), static_cast<DWORD>(bytes), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* native_handle()
|
||||||
|
{
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
if (native_handle_)
|
||||||
|
return native_handle_;
|
||||||
|
|
||||||
|
native_handle_ = ::LoadImage(nullptr, path_.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
|
||||||
|
return native_handle_;
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::experimental::filesystem::path path_;
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
void* native_handle_{nullptr};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}//end namespace detail
|
||||||
}//end namespace paint
|
}//end namespace paint
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|
||||||
|
@ -1,262 +0,0 @@
|
|||||||
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_EX_HPP
|
|
||||||
#define NANA_PAINT_DETAIL_IMAGE_ICO_EX_HPP
|
|
||||||
|
|
||||||
#include "image_pixbuf.hpp"
|
|
||||||
|
|
||||||
namespace nana {
|
|
||||||
namespace paint {
|
|
||||||
namespace detail {
|
|
||||||
// These next two structs represent how the icon information is stored
|
|
||||||
// in an ICO file.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t bWidth; // Width of the image
|
|
||||||
uint8_t bHeight; // Height of the image (times 2)
|
|
||||||
uint8_t bColorCount; // Number of colors in image (0 if >=8bpp)
|
|
||||||
uint8_t bReserved; // Reserved
|
|
||||||
uint16_t wPlanes; // Color Planes
|
|
||||||
uint16_t wBitCount; // Bits per pixel
|
|
||||||
uint32_t dwBytesInRes; // how many bytes in this resource?
|
|
||||||
uint32_t dwImageOffset; // where in the file is this image
|
|
||||||
} ICONDIRENTRY, *LPICONDIRENTRY;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint16_t idReserved; // Reserved
|
|
||||||
uint16_t idType; // resource type (1 for icons)
|
|
||||||
uint16_t idCount; // how many images?
|
|
||||||
//ICONDIRENTRY idEntries[1]; // the entries for each image
|
|
||||||
} ICONDIR, *LPICONDIR;
|
|
||||||
|
|
||||||
// size - 40 bytes
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t biSize;
|
|
||||||
uint32_t biWidth;
|
|
||||||
uint32_t biHeight; // Icon Height (added height of XOR-Bitmap and AND-Bitmap)
|
|
||||||
uint16_t biPlanes;
|
|
||||||
uint16_t biBitCount;
|
|
||||||
uint32_t biCompression;
|
|
||||||
int32_t biSizeImage;
|
|
||||||
uint32_t biXPelsPerMeter;
|
|
||||||
uint32_t biYPelsPerMeter;
|
|
||||||
uint32_t biClrUsed;
|
|
||||||
uint32_t biClrImportant;
|
|
||||||
} s_BITMAPINFOHEADER, *s_PBITMAPINFOHEADER;
|
|
||||||
|
|
||||||
// 46 bytes
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
s_BITMAPINFOHEADER icHeader; // DIB header
|
|
||||||
uint32_t icColors[1]; // Color table (short 4 bytes) //RGBQUAD
|
|
||||||
uint8_t icXOR[1]; // DIB bits for XOR mask
|
|
||||||
uint8_t icAND[1]; // DIB bits for AND mask
|
|
||||||
} ICONIMAGE, *LPICONIMAGE;
|
|
||||||
|
|
||||||
|
|
||||||
class image_ico_ex
|
|
||||||
: public basic_image_pixbuf
|
|
||||||
{
|
|
||||||
bool _m_read_ico(const void* data, std::size_t /*size*/)
|
|
||||||
{
|
|
||||||
auto width = 0;
|
|
||||||
auto height = 0;
|
|
||||||
auto buffer = (unsigned char *)data;
|
|
||||||
auto icoDir = reinterpret_cast<LPICONDIR>(buffer);
|
|
||||||
int iconsCount = icoDir->idCount;
|
|
||||||
if (icoDir->idReserved != 0 || icoDir->idType != 1 || iconsCount == 0 || iconsCount > 20)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto cursor = buffer;
|
|
||||||
cursor += 6;
|
|
||||||
auto dirEntry = reinterpret_cast<ICONDIRENTRY*>(cursor);
|
|
||||||
auto maxSize = 0;
|
|
||||||
auto offset = 0;
|
|
||||||
auto maxBitCount = 0;
|
|
||||||
for (auto i = 0; i < iconsCount; i++, ++dirEntry)
|
|
||||||
{
|
|
||||||
int w = dirEntry->bWidth;
|
|
||||||
int h = dirEntry->bHeight;
|
|
||||||
int bitCount = dirEntry->wBitCount;
|
|
||||||
if (w * h > maxSize || bitCount > maxBitCount) // we choose icon with max resolution
|
|
||||||
{
|
|
||||||
width = w;
|
|
||||||
height = h;
|
|
||||||
offset = dirEntry->dwImageOffset;
|
|
||||||
maxSize = w * h;
|
|
||||||
maxBitCount = bitCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset == 0) return false;
|
|
||||||
|
|
||||||
cursor = buffer;
|
|
||||||
cursor += offset;
|
|
||||||
auto icon = reinterpret_cast<ICONIMAGE*>(cursor);
|
|
||||||
auto realBitsCount = static_cast<int>(icon->icHeader.biBitCount);
|
|
||||||
auto hasAndMask = (realBitsCount < 32) && (height != static_cast<int>(icon->icHeader.biHeight));
|
|
||||||
cursor += 40;
|
|
||||||
pixbuf_.open(width, height);
|
|
||||||
|
|
||||||
// rgba + vertical swap
|
|
||||||
if (realBitsCount >= 32)
|
|
||||||
{
|
|
||||||
for (auto x = 0; x < width; ++x)
|
|
||||||
for (auto y = 0; y < height; ++y)
|
|
||||||
{
|
|
||||||
pixbuf_.alpha_channel(true);
|
|
||||||
auto shift2 = 4 * (x + (height - y - 1) * width);
|
|
||||||
pixel_color_t image;
|
|
||||||
image.element.red = cursor[shift2 + 2];
|
|
||||||
image.element.green = cursor[shift2 + 1];
|
|
||||||
image.element.blue = cursor[shift2];
|
|
||||||
image.element.alpha_channel = cursor[shift2 + 3];
|
|
||||||
pixbuf_.pixel(x, y, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (realBitsCount == 24)
|
|
||||||
{
|
|
||||||
for (auto x = 0; x < width; x++)
|
|
||||||
for (auto y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
pixbuf_.alpha_channel(true);
|
|
||||||
auto shift2 = 3 * (x + (height - y - 1) * width);
|
|
||||||
pixel_color_t image;
|
|
||||||
image.element.red = cursor[shift2 + 2];
|
|
||||||
image.element.green = cursor[shift2 + 1];
|
|
||||||
image.element.blue = cursor[shift2];
|
|
||||||
image.element.alpha_channel = 255;
|
|
||||||
pixbuf_.pixel(x, y, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (realBitsCount == 8) /// 256 colors
|
|
||||||
{
|
|
||||||
// 256 color table
|
|
||||||
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
|
||||||
cursor += 256 * 4;
|
|
||||||
for (auto x = 0; x < width; x++)
|
|
||||||
for (auto y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
pixbuf_.alpha_channel(true);
|
|
||||||
|
|
||||||
auto shift2 = (x + (height - y - 1) * width);
|
|
||||||
auto index = 4 * cursor[shift2];
|
|
||||||
pixel_color_t image;
|
|
||||||
image.element.red = colors[index + 2];
|
|
||||||
image.element.green = colors[index + 1];
|
|
||||||
image.element.blue = colors[index];
|
|
||||||
image.element.alpha_channel = 255;
|
|
||||||
pixbuf_.pixel(x, y, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (realBitsCount == 4) /// 16 colors
|
|
||||||
{
|
|
||||||
// 16 color table
|
|
||||||
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
|
||||||
cursor += 16 * 4;
|
|
||||||
for (auto x = 0; x < width; x++)
|
|
||||||
for (auto y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
auto shift2 = (x + (height - y - 1) * width);
|
|
||||||
auto index = cursor[shift2 / 2];
|
|
||||||
if (shift2 % 2 == 0)
|
|
||||||
index = (index >> 4) & 0xF;
|
|
||||||
else
|
|
||||||
index = index & 0xF;
|
|
||||||
index *= 4;
|
|
||||||
pixbuf_.alpha_channel(true);
|
|
||||||
pixel_color_t image;
|
|
||||||
image.element.red = colors[index + 2];
|
|
||||||
image.element.green = colors[index + 1];
|
|
||||||
image.element.blue = colors[index];
|
|
||||||
image.element.alpha_channel = 255;
|
|
||||||
pixbuf_.pixel(x, y, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (realBitsCount == 1) /// 2 colors
|
|
||||||
{
|
|
||||||
// 2 color table
|
|
||||||
auto colors = reinterpret_cast<unsigned char *>(cursor);
|
|
||||||
cursor += 2 * 4;
|
|
||||||
auto boundary = width; //!!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
|
|
||||||
while (boundary % 32 != 0) boundary++;
|
|
||||||
for (auto x = 0; x < width; x++)
|
|
||||||
for (auto y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
auto shift2 = (x + (height - y - 1) * boundary);
|
|
||||||
auto index = cursor[shift2 / 8];
|
|
||||||
|
|
||||||
// select 1 bit only
|
|
||||||
unsigned char bit = 7 - (x % 8);
|
|
||||||
index = (index >> bit) & 0x01;
|
|
||||||
index *= 4;
|
|
||||||
pixbuf_.alpha_channel(true);
|
|
||||||
pixel_color_t image;
|
|
||||||
image.element.red = colors[index + 2];
|
|
||||||
image.element.green = colors[index + 1];
|
|
||||||
image.element.blue = colors[index];
|
|
||||||
image.element.alpha_channel = 255;
|
|
||||||
pixbuf_.pixel(x, y, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read AND mask after base color data - 1 BIT MASK
|
|
||||||
if (hasAndMask)
|
|
||||||
{
|
|
||||||
auto boundary = width * realBitsCount; //!!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
|
|
||||||
while (boundary % 32 != 0) boundary++;
|
|
||||||
cursor += boundary * height / 8;
|
|
||||||
boundary = width;
|
|
||||||
while (boundary % 32 != 0) boundary++;
|
|
||||||
for (auto y = 0; y < height; y++)
|
|
||||||
for (auto x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
unsigned char bit = 7 - (x % 8);
|
|
||||||
auto shift2 = (x + (height - y - 1) * boundary) / 8;
|
|
||||||
auto mask = (0x01 & (static_cast<unsigned char>(cursor[shift2]) >> bit));
|
|
||||||
auto pc = pixbuf_.pixel(x, y);
|
|
||||||
auto alpha = pc.element.alpha_channel;
|
|
||||||
alpha *= 1 - mask;
|
|
||||||
pc.element.alpha_channel = alpha;
|
|
||||||
pixbuf_.pixel(x, y, pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool open(const std::experimental::filesystem::path& ico_file) override
|
|
||||||
{
|
|
||||||
std::ifstream file(ico_file.string(), std::ios::binary);
|
|
||||||
if (!file.is_open()) return false;
|
|
||||||
|
|
||||||
// allocates a buffer for the image
|
|
||||||
file.seekg(0, std::ios::end);
|
|
||||||
const auto bytes = static_cast<std::size_t>(file.tellg());
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
auto buffer = new char[bytes];
|
|
||||||
|
|
||||||
// read data from the file and set them in the buffer
|
|
||||||
file.read(buffer, bytes);
|
|
||||||
auto okret = _m_read_ico(buffer, bytes);
|
|
||||||
|
|
||||||
// delete buffer and return
|
|
||||||
delete[] buffer;
|
|
||||||
return okret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open(const void* data, std::size_t bytes) override
|
|
||||||
{
|
|
||||||
return _m_read_ico(data, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}//end namespace detail
|
|
||||||
}//end namespace paint
|
|
||||||
}//end namespace nana
|
|
||||||
|
|
||||||
#endif
|
|
123
source/paint/detail/image_ico_resource.hpp
Normal file
123
source/paint/detail/image_ico_resource.hpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Icon Resource
|
||||||
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
|
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* @file: nana/paint/detail/image_ico_resource.hpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_RESOURCE_INCLUDED
|
||||||
|
#define NANA_PAINT_DETAIL_IMAGE_ICO_RESOURCE_INCLUDED
|
||||||
|
|
||||||
|
#include <nana/filesystem/filesystem_ext.hpp>
|
||||||
|
#include <nana/paint/detail/image_impl_interface.hpp>
|
||||||
|
#include <nana/paint/graphics.hpp>
|
||||||
|
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nana{ namespace paint
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
class image_ico_resource
|
||||||
|
:public image::image_impl_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool open(const std::experimental::filesystem::path& filename) override
|
||||||
|
{
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
SHFILEINFO sfi;
|
||||||
|
::SHGetFileInfo(filename.c_str(), 0, &sfi, sizeof sfi, SHGFI_ICON);
|
||||||
|
|
||||||
|
native_handle_ = sfi.hIcon;
|
||||||
|
#endif
|
||||||
|
return (nullptr != native_handle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const void* data, std::size_t bytes) override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alpha_channel() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const override
|
||||||
|
{
|
||||||
|
return !native_handle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() override
|
||||||
|
{
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
if (native_handle_)
|
||||||
|
::DestroyIcon(reinterpret_cast<HICON>(native_handle_));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
nana::size size() const override
|
||||||
|
{
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
ICONINFO info;
|
||||||
|
if ((!native_handle_) || !::GetIconInfo(reinterpret_cast<HICON>(native_handle_), &info))
|
||||||
|
return{};
|
||||||
|
|
||||||
|
::nana::size sz{
|
||||||
|
info.xHotspot << 1,
|
||||||
|
info.yHotspot << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
::DeleteObject(info.hbmColor);
|
||||||
|
::DeleteObject(info.hbmMask);
|
||||||
|
return sz;
|
||||||
|
#else
|
||||||
|
return{};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override
|
||||||
|
{
|
||||||
|
if (!native_handle_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
::DrawIconEx(graph.handle()->context, p_dst.x, p_dst.y, reinterpret_cast<HICON>(native_handle_), src_r.width, src_r.height, 0, 0, DI_NORMAL);
|
||||||
|
#else
|
||||||
|
static_cast<void>(src_r); //eliminate unused parameter compiler warning.
|
||||||
|
static_cast<void>(p_dst);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const override
|
||||||
|
{
|
||||||
|
if (!native_handle_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
|
::DrawIconEx(graph.handle()->context, r.x, r.y, reinterpret_cast<HICON>(native_handle_), r.width, r.height, 0, 0, DI_NORMAL);
|
||||||
|
#else
|
||||||
|
static_cast<void>(r); //eliminate unused parameter compiler warning.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* native_handle()
|
||||||
|
{
|
||||||
|
return native_handle_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void* native_handle_;
|
||||||
|
};//end class image_ico
|
||||||
|
}
|
||||||
|
}//end namespace paint
|
||||||
|
}//end namespace nana
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Paint Image Implementation
|
* Paint Image Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -11,6 +11,7 @@
|
|||||||
* @contributors:
|
* @contributors:
|
||||||
* nabijaczleweli(pr#106)
|
* nabijaczleweli(pr#106)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nana/push_ignore_diagnostic>
|
#include <nana/push_ignore_diagnostic>
|
||||||
#include <nana/detail/platform_spec_selector.hpp>
|
#include <nana/detail/platform_spec_selector.hpp>
|
||||||
#include <nana/paint/image.hpp>
|
#include <nana/paint/image.hpp>
|
||||||
@ -32,10 +33,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "detail/image_bmp.hpp"
|
#include "detail/image_bmp.hpp"
|
||||||
#include "detail/image_ico.hpp"
|
|
||||||
|
|
||||||
#include "image_accessor.hpp"
|
#include "image_accessor.hpp"
|
||||||
#include "detail/image_ico_ex.hpp"
|
#include "detail/image_ico_resource.hpp"
|
||||||
|
#include "detail/image_ico.hpp"
|
||||||
|
|
||||||
namespace fs = std::experimental::filesystem;
|
namespace fs = std::experimental::filesystem;
|
||||||
|
|
||||||
@ -46,9 +47,14 @@ namespace paint
|
|||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
HICON image_accessor::icon(const nana::paint::image& img)
|
HICON image_accessor::icon(const nana::paint::image& img)
|
||||||
{
|
{
|
||||||
|
auto ico_res = dynamic_cast<paint::detail::image_ico_resource*>(img.image_ptr_.get());
|
||||||
|
if (ico_res)
|
||||||
|
return reinterpret_cast<HICON>(ico_res->native_handle());
|
||||||
|
|
||||||
auto ico = dynamic_cast<paint::detail::image_ico*>(img.image_ptr_.get());
|
auto ico = dynamic_cast<paint::detail::image_ico*>(img.image_ptr_.get());
|
||||||
if (ico && ico->ptr())
|
if (ico)
|
||||||
return *(ico->ptr());
|
return reinterpret_cast<HICON>(ico->native_handle());
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -58,138 +64,6 @@ namespace paint
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
//class image_ico
|
|
||||||
image_ico::image_ico(bool is_ico): is_ico_(is_ico){}
|
|
||||||
|
|
||||||
bool image_ico::open(const fs::path& file)
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
HICON handle = 0;
|
|
||||||
if(is_ico_)
|
|
||||||
{
|
|
||||||
handle = (HICON)::LoadImage(0, file.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHFILEINFO sfi;
|
|
||||||
::SHGetFileInfo(file.c_str(), 0, &sfi, sizeof(sfi), SHGFI_ICON);
|
|
||||||
handle = sfi.hIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(handle)
|
|
||||||
{
|
|
||||||
HICON * p = new HICON(handle);
|
|
||||||
ptr_ = std::shared_ptr<HICON>(p, handle_deleter());
|
|
||||||
ICONINFO info;
|
|
||||||
::GetIconInfo(handle, &info);
|
|
||||||
size_.width = (info.xHotspot << 1);
|
|
||||||
size_.height = (info.yHotspot << 1);
|
|
||||||
|
|
||||||
::DeleteObject(info.hbmColor);
|
|
||||||
::DeleteObject(info.hbmMask);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static_cast<void>(is_ico_); //eliminate the unused compiler warning in Linux.
|
|
||||||
static_cast<void>(file); //to eliminate the unused parameter compiler warning.
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool image_ico::open(const void* data, std::size_t bytes)
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
// use actual resource size, stopped using CreateIconFromResource since it loads blurry image
|
|
||||||
HICON handle = ::CreateIconFromResourceEx((PBYTE)data, static_cast<DWORD>(bytes), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR);
|
|
||||||
if(handle)
|
|
||||||
{
|
|
||||||
ICONINFO info;
|
|
||||||
if (::GetIconInfo(handle, &info) != 0)
|
|
||||||
{
|
|
||||||
HICON * p = new HICON(handle);
|
|
||||||
ptr_ = std::shared_ptr<HICON>(p, handle_deleter());
|
|
||||||
size_.width = (info.xHotspot << 1);
|
|
||||||
size_.height = (info.yHotspot << 1);
|
|
||||||
::DeleteObject(info.hbmColor);
|
|
||||||
::DeleteObject(info.hbmMask);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static_cast<void>(is_ico_); //kill the unused compiler warning in Linux.
|
|
||||||
static_cast<void>(data); //to eliminate unused parameter compiler warning.
|
|
||||||
static_cast<void>(bytes);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool image_ico::alpha_channel() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool image_ico::empty() const
|
|
||||||
{
|
|
||||||
return (nullptr == ptr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void image_ico::close()
|
|
||||||
{
|
|
||||||
ptr_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
nana::size image_ico::size() const
|
|
||||||
{
|
|
||||||
return size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void image_ico::paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const
|
|
||||||
{
|
|
||||||
if(ptr_ && (graph.empty() == false))
|
|
||||||
{
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
::DrawIconEx(graph.handle()->context, p_dst.x, p_dst.y, *ptr_, src_r.width, src_r.height, 0, 0, DI_NORMAL);
|
|
||||||
#else
|
|
||||||
static_cast<void>(src_r); //eliminate unused parameter compiler warning.
|
|
||||||
static_cast<void>(p_dst);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void image_ico::stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const
|
|
||||||
{
|
|
||||||
if(ptr_ && (graph.empty() == false))
|
|
||||||
{
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
::DrawIconEx(graph.handle()->context, r.x, r.y, *ptr_, r.width, r.height, 0, 0, DI_NORMAL);
|
|
||||||
#else
|
|
||||||
static_cast<void>(r); //eliminate unused parameter compiler warning.
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const image_ico::ptr_t& image_ico::ptr() const
|
|
||||||
{
|
|
||||||
return ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
//struct handle_deleter
|
|
||||||
void image_ico::handle_deleter::operator()(HICON* p) const
|
|
||||||
{
|
|
||||||
if(p && *p)
|
|
||||||
::DestroyIcon(*p);
|
|
||||||
delete p;
|
|
||||||
}
|
|
||||||
//end struct handle_deleter
|
|
||||||
#endif
|
|
||||||
//end class image_ico
|
|
||||||
}
|
|
||||||
|
|
||||||
image::image_impl_interface::~image_impl_interface()
|
image::image_impl_interface::~image_impl_interface()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -265,7 +139,7 @@ namespace paint
|
|||||||
{
|
{
|
||||||
if (ext_ico == ext)
|
if (ext_ico == ext)
|
||||||
{
|
{
|
||||||
ptr = std::make_shared<detail::image_ico_ex>();
|
ptr = std::make_shared<detail::image_ico>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +179,7 @@ namespace paint
|
|||||||
if (*reinterpret_cast<const short*>("BM") == meta)
|
if (*reinterpret_cast<const short*>("BM") == meta)
|
||||||
ptr = std::make_shared<detail::image_bmp>();
|
ptr = std::make_shared<detail::image_bmp>();
|
||||||
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
||||||
ptr = std::make_shared<detail::image_ico>(false);
|
ptr = std::make_shared<detail::image_ico_resource>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +213,7 @@ namespace paint
|
|||||||
if (*reinterpret_cast<const short*>("BM") == meta)
|
if (*reinterpret_cast<const short*>("BM") == meta)
|
||||||
ptr = std::make_shared<detail::image_bmp>();
|
ptr = std::make_shared<detail::image_bmp>();
|
||||||
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
||||||
ptr = std::make_shared<detail::image_ico>(false);
|
ptr = std::make_shared<detail::image_ico_resource>();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bytes > 8 && (0x474e5089 == *reinterpret_cast<const unsigned*>(data)))
|
if (bytes > 8 && (0x474e5089 == *reinterpret_cast<const unsigned*>(data)))
|
||||||
@ -357,16 +231,16 @@ namespace paint
|
|||||||
else if (bytes > 9 && (0x66697845 == *reinterpret_cast<const unsigned*>(reinterpret_cast<const char*>(data)+5))) //Exif
|
else if (bytes > 9 && (0x66697845 == *reinterpret_cast<const unsigned*>(reinterpret_cast<const char*>(data)+5))) //Exif
|
||||||
ptr = std::make_shared<detail::image_jpeg>();
|
ptr = std::make_shared<detail::image_jpeg>();
|
||||||
#endif
|
#endif
|
||||||
|
if ((!ptr) && (bytes > 40))
|
||||||
#if defined(NANA_WINDOWS)
|
{
|
||||||
// suppose icon data is bitmap data
|
switch (*reinterpret_cast<const unsigned*>(data))
|
||||||
if (!ptr && bytes > 40 /* sizeof(BITMAPINFOHEADER) */ && (40 == *reinterpret_cast<const uint32_t*>(data))) {
|
{
|
||||||
ptr = std::make_shared<detail::image_ico>(true);
|
case 40:
|
||||||
|
case 0x00010000:
|
||||||
|
if (!ptr && bytes > 40)
|
||||||
|
ptr = std::make_shared<detail::image_ico>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (!ptr && bytes > 40 && (0x00010000 == *reinterpret_cast<const unsigned*>(data)))
|
|
||||||
ptr = std::make_shared<detail::image_ico_ex>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user