Merge branch 'hotfix-1.7.3' into develop
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Bitmap Format Graphics Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2020 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -14,6 +14,7 @@
|
||||
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include "image_pixbuf.hpp"
|
||||
|
||||
namespace nana{ namespace paint
|
||||
@@ -106,7 +107,7 @@ namespace nana{ namespace paint
|
||||
if (16 <= header->biBitCount)
|
||||
pixbuf_.put(bits, header->biWidth, bmp_height, header->biBitCount, bytes_per_line, (header->biHeight < 0));
|
||||
else
|
||||
_m_put_with_palette(header, bits, bytes_per_line);
|
||||
_m_put_with_palette(header, bits, bmp_file->bfSize - bmp_file->bfOffBits, bytes_per_line);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -132,7 +133,72 @@ namespace nana{ namespace paint
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
void _m_put_with_palette(const bitmap_info_header* header, const unsigned char* pixel_indexes, unsigned line_bytes)
|
||||
std::unique_ptr<unsigned char[]> _m_decompress_rle8(const bitmap_info_header* header, const unsigned char* data, std::size_t data_size)
|
||||
{
|
||||
std::size_t const lines = std::abs(header->biHeight);
|
||||
unsigned char* const indexes = new unsigned char[header->biWidth * lines];
|
||||
auto p = indexes;
|
||||
auto p_line = p;
|
||||
auto const p_end = indexes + header->biWidth * lines;
|
||||
|
||||
std::size_t line_pos = 0;
|
||||
auto end = data + data_size;
|
||||
while (data != end && p < p_end)
|
||||
{
|
||||
if (0 == data[0])
|
||||
{
|
||||
//escape
|
||||
if (0 == data[1])
|
||||
{
|
||||
//eol
|
||||
data += 2;
|
||||
++line_pos;
|
||||
}
|
||||
else if (1 == data[1])
|
||||
{
|
||||
//eof
|
||||
data += 2;
|
||||
break;
|
||||
}
|
||||
else if (2 == data[1])
|
||||
{
|
||||
//delta
|
||||
auto x = data[2];
|
||||
auto y = data[3];
|
||||
|
||||
// Check if the delta is available
|
||||
if ((p + x < p_line + header->biWidth) && (line_pos + y < lines))
|
||||
{
|
||||
p += y * header->biWidth + x;
|
||||
line_pos += y;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
data += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
//absolute
|
||||
std::memcpy(p, data + 2, data[1]);
|
||||
p += data[1];
|
||||
|
||||
data += ((data[1] + 1) & 0xFFE) + 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memset(p, data[1], data[0]);
|
||||
p += data[0];
|
||||
|
||||
data += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return std::unique_ptr<unsigned char[]>{ indexes };
|
||||
}
|
||||
|
||||
void _m_put_with_palette(const bitmap_info_header* header, const unsigned char* bits, std::size_t length, unsigned line_bytes)
|
||||
{
|
||||
auto const image_height = std::abs(header->biHeight);
|
||||
const std::size_t total_pixels = header->biWidth * static_cast<std::size_t>(image_height);
|
||||
@@ -152,9 +218,19 @@ namespace nana{ namespace paint
|
||||
|
||||
if (8 == header->biBitCount)
|
||||
{
|
||||
//decompressed indexes
|
||||
std::unique_ptr<unsigned char[]> indexes;
|
||||
|
||||
if (1 == header->biCompression)
|
||||
{
|
||||
indexes = _m_decompress_rle8(header, bits, length);
|
||||
line_bytes = header->biWidth;
|
||||
bits = indexes.get();
|
||||
}
|
||||
|
||||
while (dst_px < end_dst_px)
|
||||
{
|
||||
auto px_indexes = pixel_indexes + line_bytes * line_pos;
|
||||
auto px_indexes = bits + line_bytes * line_pos;
|
||||
auto const line_end_dst_px = dst_px + header->biWidth;
|
||||
while (dst_px != line_end_dst_px)
|
||||
{
|
||||
@@ -173,7 +249,7 @@ namespace nana{ namespace paint
|
||||
{
|
||||
while (dst_px < end_dst_px)
|
||||
{
|
||||
auto px_indexes = pixel_indexes + line_bytes * line_pos;
|
||||
auto px_indexes = bits + line_bytes * line_pos;
|
||||
auto const line_end_dst_px = dst_px + header->biWidth;
|
||||
std::size_t pos = 0;
|
||||
switch (header->biBitCount)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Paint Image Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2020 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -108,155 +108,72 @@ namespace paint
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::shared_ptr<image::image_impl_interface> create_image(const fs::path & p)
|
||||
// Check file type through file format signature
|
||||
std::shared_ptr<image::image_impl_interface> create_image(const char* buf, std::size_t len)
|
||||
{
|
||||
std::shared_ptr<image::image_impl_interface> ptr;
|
||||
|
||||
auto ext = p.extension().native();
|
||||
if (ext.empty())
|
||||
return ptr;
|
||||
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), [](int ch)
|
||||
if (buf && len >= 8)
|
||||
{
|
||||
if ('A' <= ch && ch <= 'Z')
|
||||
ch -= ('A' - 'a');
|
||||
return ch;
|
||||
});
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
const wchar_t* ext_ico = L".ico";
|
||||
const wchar_t* ext_png = L".png";
|
||||
const wchar_t* ext_jpg = L".jpg";
|
||||
const wchar_t* ext_jpeg = L".jpeg";
|
||||
#else
|
||||
const char* ext_ico = ".ico";
|
||||
const char* ext_png = ".png";
|
||||
const char* ext_jpg = ".jpg";
|
||||
const char* ext_jpeg = ".jpeg";
|
||||
#endif
|
||||
do
|
||||
{
|
||||
if (ext_ico == ext)
|
||||
if (std::strncmp("\x00\x00\x01\x00", buf, 4) == 0)
|
||||
{
|
||||
ptr = std::make_shared<detail::image_ico>();
|
||||
break;
|
||||
return std::make_shared<detail::image_ico>();
|
||||
}
|
||||
|
||||
if (ext_png == ext)
|
||||
else if (std::strncmp(buf, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0)
|
||||
{
|
||||
#if defined(NANA_ENABLE_PNG)
|
||||
ptr = std::make_shared<detail::image_png>();
|
||||
#else
|
||||
return ptr;
|
||||
return std::make_shared<detail::image_png>();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (ext_jpg == ext || ext_jpeg == ext)
|
||||
else if (std::strncmp("\xFF\xD8\xFF", buf, 3) == 0)
|
||||
{
|
||||
#if defined(NANA_ENABLE_JPEG)
|
||||
ptr = std::make_shared<detail::image_jpeg>();
|
||||
#else
|
||||
return ptr;
|
||||
return std::make_shared<detail::image_jpeg>();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
else if (*reinterpret_cast<const short*>("BM") == *reinterpret_cast<const short*>(buf))
|
||||
return std::make_shared<detail::image_bmp>();
|
||||
else if (*reinterpret_cast<const short*>("MZ") == *reinterpret_cast<const short*>(buf))
|
||||
return std::make_shared<detail::image_ico_resource>();
|
||||
}
|
||||
|
||||
//Check for BMP
|
||||
if (!ptr)
|
||||
{
|
||||
#ifndef NANA_MINGW
|
||||
std::ifstream ifs(p.c_str(), std::ios::binary);
|
||||
#else
|
||||
std::ifstream ifs(to_osmbstr(to_utf8(p.native())).c_str(), std::ios::binary);
|
||||
#endif
|
||||
if (ifs)
|
||||
{
|
||||
unsigned short meta = 0;
|
||||
ifs.read(reinterpret_cast<char*>(&meta), 2);
|
||||
if (*reinterpret_cast<const short*>("BM") == meta)
|
||||
ptr = std::make_shared<detail::image_bmp>();
|
||||
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
||||
ptr = std::make_shared<detail::image_ico_resource>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
bool image::open(const ::std::string& img)
|
||||
{
|
||||
fs::path p(img);
|
||||
image_ptr_.reset();
|
||||
|
||||
std::ifstream file{ p, std::ios::binary };
|
||||
if (file)
|
||||
{
|
||||
char buf[8];
|
||||
if (file.read(buf, 8).gcount() == 8)
|
||||
image_ptr_ = create_image(buf, 8);
|
||||
}
|
||||
|
||||
return (image_ptr_ ? image_ptr_->open(p) : false);
|
||||
}
|
||||
|
||||
bool image::open(const ::std::string& file)
|
||||
bool image::open(const std::wstring& img)
|
||||
{
|
||||
fs::path path(file);
|
||||
image_ptr_ = create_image(path);
|
||||
return (image_ptr_ ? image_ptr_->open(path) : false);
|
||||
}
|
||||
fs::path p(img);
|
||||
image_ptr_.reset();
|
||||
|
||||
bool image::open(const std::wstring& file)
|
||||
{
|
||||
fs::path path(file);
|
||||
image_ptr_ = create_image(path);
|
||||
return (image_ptr_ ? image_ptr_->open(path) : false);
|
||||
std::ifstream file{ p, std::ios::binary };
|
||||
if (file)
|
||||
{
|
||||
char buf[8];
|
||||
if (file.read(buf, 8).gcount() == 8)
|
||||
image_ptr_ = create_image(buf, 8);
|
||||
}
|
||||
|
||||
return (image_ptr_ ? image_ptr_->open(p) : false);
|
||||
}
|
||||
|
||||
bool image::open(const void* data, std::size_t bytes)
|
||||
{
|
||||
close();
|
||||
|
||||
if (bytes > 2)
|
||||
{
|
||||
std::shared_ptr<image::image_impl_interface> ptr;
|
||||
|
||||
auto meta = *reinterpret_cast<const unsigned short*>(data);
|
||||
|
||||
if (*reinterpret_cast<const short*>("BM") == meta)
|
||||
ptr = std::make_shared<detail::image_bmp>();
|
||||
else if (*reinterpret_cast<const short*>("MZ") == meta)
|
||||
ptr = std::make_shared<detail::image_ico_resource>();
|
||||
else
|
||||
{
|
||||
if (bytes > 8 && (0x474e5089 == *reinterpret_cast<const unsigned*>(data)))
|
||||
{
|
||||
#if defined(NANA_ENABLE_PNG)
|
||||
ptr = std::make_shared<detail::image_png>();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(NANA_ENABLE_JPEG)
|
||||
if ((bytes > 11) && (0xd8ff == *reinterpret_cast<const unsigned short*>(data)))
|
||||
{
|
||||
switch(*reinterpret_cast<const unsigned*>(reinterpret_cast<const char*>(data)+6))
|
||||
{
|
||||
case 0x4649464A: //JFIF
|
||||
case 0x66697845: //Exif
|
||||
ptr = std::make_shared<detail::image_jpeg>();
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((!ptr) && (bytes > 40))
|
||||
{
|
||||
switch (*reinterpret_cast<const unsigned*>(data))
|
||||
{
|
||||
case 40:
|
||||
case 0x00010000:
|
||||
if (!ptr && bytes > 40)
|
||||
ptr = std::make_shared<detail::image_ico>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
image_ptr_.swap(ptr);
|
||||
return image_ptr_->open(data, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
image_ptr_ = create_image(static_cast<const char*>(data), bytes);
|
||||
return (image_ptr_ ? image_ptr_->open(data, bytes) : false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user