open bmp image with memory buffer

This commit is contained in:
Jinhao 2016-01-28 01:36:45 +08:00
parent 3c8ee33ae8
commit 1c938a06fd

View File

@ -1,7 +1,7 @@
/* /*
* Bitmap Format Graphics Implementation * Bitmap Format Graphics Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2016 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
@ -14,14 +14,12 @@
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP #define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
#include "image_pixbuf.hpp" #include "image_pixbuf.hpp"
#include <memory> #include <memory>
namespace nana{ namespace paint namespace nana{ namespace paint
{ {
namespace detail namespace detail
{ {
#ifndef NANA_WINDOWS #ifndef NANA_WINDOWS
struct bitmap_file_header struct bitmap_file_header
{ {
@ -78,32 +76,14 @@ namespace nana{ namespace paint
bool open(const void* data, std::size_t bytes) override bool open(const void* data, std::size_t bytes) override
{ {
// TODO: read a BMP file from memory auto bmp_data = reinterpret_cast<const char*>(data);
return false;
}
bool open(const nana::experimental::filesystem::path& filename) override auto header = reinterpret_cast<const bitmap_file_header*>(bmp_data);
{ if ((header->bfType != 0x4D42) || (header->bfSize != bytes))
std::ifstream ifs(filename.string(), std::ios::binary);
if(ifs)
{
ifs.seekg(0, std::ios::end);
auto size = ifs.tellg();
ifs.seekg(0, std::ios::beg);
if(size <= static_cast<int>(sizeof(bitmap_file_header)))
return false; return false;
std::unique_ptr<char[]> buffer(new char[static_cast<int>(size)]); auto bits = reinterpret_cast<const unsigned char*>(bmp_data + header->bfOffBits);
auto info = reinterpret_cast<const bitmap_info *>(header + 1);
ifs.read(buffer.get(), size);
if(size == ifs.gcount())
{
bitmap_file_header * header = reinterpret_cast<bitmap_file_header*>(buffer.get());
if((header->bfType == 0x4D42) && (static_cast<std::streamsize>(header->bfSize) == size))
{
unsigned char* bits = reinterpret_cast<unsigned char*>(buffer.get() + header->bfOffBits);
bitmap_info * info = reinterpret_cast<bitmap_info *>(header + 1);
//Bitmap file is 4byte-aligned for each line. //Bitmap file is 4byte-aligned for each line.
std::size_t bytes_per_line; std::size_t bytes_per_line;
@ -135,7 +115,7 @@ namespace nana{ namespace paint
auto s_p = s; auto s_p = s;
while (d_p != dpend) while (d_p != dpend)
{ {
rgb_quad & rgb = info->bmiColors[*s_p++]; auto & rgb = info->bmiColors[*s_p++];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
d_p->element.blue = rgb.rgbBlue; d_p->element.blue = rgb.rgbBlue;
@ -156,7 +136,7 @@ namespace nana{ namespace paint
const auto * s_p = s; const auto * s_p = s;
while (d_p != dpend) while (d_p != dpend)
{ {
rgb_quad & rgb = info->bmiColors[*s_p++]; auto & rgb = info->bmiColors[*s_p++];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
d_p->element.blue = rgb.rgbBlue; d_p->element.blue = rgb.rgbBlue;
@ -181,7 +161,7 @@ namespace nana{ namespace paint
unsigned index = 0; unsigned index = 0;
while (d_p != dpend) while (d_p != dpend)
{ {
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4]; auto & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -205,7 +185,7 @@ namespace nana{ namespace paint
unsigned index = 0; unsigned index = 0;
while (d_p != dpend) while (d_p != dpend)
{ {
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4]; auto & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -233,7 +213,7 @@ namespace nana{ namespace paint
while (d_p != dpend) while (d_p != dpend)
{ {
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2 unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift]; auto& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift)) >> shift];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -258,7 +238,7 @@ namespace nana{ namespace paint
while (d_p != dpend) while (d_p != dpend)
{ {
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2 unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift]; auto& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift)) >> shift];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -286,7 +266,7 @@ namespace nana{ namespace paint
while (d_p != dpend) while (d_p != dpend)
{ {
unsigned bi = (7 - (index & 7)); //(index % 8) unsigned bi = (7 - (index & 7)); //(index % 8)
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi]; auto & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -311,7 +291,7 @@ namespace nana{ namespace paint
while (d_p != dpend) while (d_p != dpend)
{ {
unsigned bi = (7 - (index & 7)); unsigned bi = (7 - (index & 7));
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi]; auto & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
d_p->element.red = rgb.rgbRed; d_p->element.red = rgb.rgbRed;
d_p->element.green = rgb.rgbGreen; d_p->element.green = rgb.rgbGreen;
@ -325,10 +305,29 @@ namespace nana{ namespace paint
} }
} }
} }
return true;
} }
bool open(const nana::experimental::filesystem::path& filename) override
{
std::ifstream ifs(filename.string(), std::ios::binary);
if(ifs)
{
ifs.seekg(0, std::ios::end);
auto size = ifs.tellg();
ifs.seekg(0, std::ios::beg);
if(size <= static_cast<int>(sizeof(bitmap_file_header)))
return false;
std::unique_ptr<char[]> buffer(new char[static_cast<int>(size)]);
ifs.read(buffer.get(), size);
if (size == ifs.gcount())
return open(buffer.get(), size);
} }
} return false;
return (false == pixbuf_.empty());
} }
bool alpha_channel() const override bool alpha_channel() const override