improve image and pixel_buffer

This commit is contained in:
Jinhao
2015-10-17 14:42:07 +08:00
parent 8f59ccfbf6
commit 7f4cc3f6d9
13 changed files with 216 additions and 266 deletions

View File

@@ -13,7 +13,8 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_BMP_HPP
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
#include <nana/paint/detail/image_impl_interface.hpp>
#include "image_pixbuf.hpp"
#include <memory>
namespace nana{ namespace paint
@@ -65,7 +66,7 @@ namespace nana{ namespace paint
#endif
class image_bmp
:public image::image_impl_interface
:public basic_image_pixbuf
{
public:
image_bmp(){}
@@ -340,35 +341,6 @@ namespace nana{ namespace paint
{
return false;
}
bool empty() const override
{
return pixbuf_.empty();
}
void close() override
{
pixbuf_.close();
}
nana::size size() const override
{
return pixbuf_.size();
}
void paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override
{
if(graph && pixbuf_)
pixbuf_.paste(src_r, graph.handle(), p_dst);
}
void stretch(const nana::rectangle& src_r, graph_reference graph, const nana::rectangle& r) const override
{
if(graph && pixbuf_)
pixbuf_.stretch(src_r, graph.handle(), r);
}
private:
nana::paint::pixel_buffer pixbuf_;
};//end class bmpfile
}//end namespace detail
}//end namespace paint

View File

@@ -0,0 +1,63 @@
/*
* Basic Image PixelBuffer Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2015 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_pixbuf.hpp
*/
#ifndef NANA_PAINT_DETAIL_IMAGE_PIXBUF_HPP
#define NANA_PAINT_DETAIL_IMAGE_PIXBUF_HPP
#include <nana/paint/detail/image_impl_interface.hpp>
#include <nana/paint/pixel_buffer.hpp>
namespace nana
{
namespace paint{ namespace detail{
class basic_image_pixbuf
: public image::image_impl_interface
{
public:
bool alpha_channel() const override
{
return pixbuf_.alpha_channel();
}
bool empty() const override
{
return pixbuf_.empty();
}
void close() override
{
pixbuf_.close();
}
::nana::size size() const override
{
return pixbuf_.size();
}
void paste(const ::nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override
{
pixbuf_.paste(src_r, graph.handle(), p_dst);
}
void stretch(const ::nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const override
{
pixbuf_.stretch(src_r, dst.handle(), r);
}
protected:
pixel_buffer pixbuf_;
};
}//end namespace detail
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -1,7 +1,7 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_PNG_HPP
#define NANA_PAINT_DETAIL_IMAGE_PNG_HPP
#include <nana/paint/detail/image_impl_interface.hpp>
#include "image_pixbuf.hpp"
//Separate the libpng from the package that system provides.
#if defined(NANA_LIBPNG)
@@ -11,14 +11,13 @@
#endif
#include <stdio.h>
#include <nana/paint/pixel_buffer.hpp>
namespace nana
{
namespace paint{ namespace detail{
class image_png
: public image::image_impl_interface
: public basic_image_pixbuf
{
public:
bool open(const nana::char_t* png_file) override
@@ -164,39 +163,6 @@ namespace nana
throw std::logic_error("PNG is not supported for raw data buffer");
return false;
}
bool alpha_channel() const override
{
return pixbuf_.alpha_channel();
}
virtual bool empty() const override
{
return pixbuf_.empty();
}
virtual void close() override
{
pixbuf_.close();
}
virtual nana::size size() const override
{
return pixbuf_.size();
}
void paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override
{
pixbuf_.paste(src_r, graph.handle(), p_dst);
}
void stretch(const nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const override
{
pixbuf_.stretch(src_r, dst.handle(), r);
}
private:
nana::paint::pixel_buffer pixbuf_;
};
}//end namespace detail
}//end namespace paint

View File

@@ -20,9 +20,12 @@
#include <nana/paint/detail/image_impl_interface.hpp>
#include <nana/paint/pixel_buffer.hpp>
#if defined(NANA_ENABLE_PNG)
#include "detail/image_png.hpp"
#endif
#include "detail/image_bmp.hpp"
#include "detail/image_ico.hpp"
@@ -155,16 +158,17 @@ namespace paint
image::image_impl_interface::~image_impl_interface()
{}
namespace detail
/*
namespace detail
{
int toupper(int c)
int toupper(int c) //deprecated
{
return (('a' <= c && c <= 'z') ?
c - ('a' - 'A')
: c);
}
}//end namespace detail
//*/
//class image
image::image()
@@ -216,25 +220,48 @@ namespace paint
if(filename.size())
{
nana::string fn;
std::transform(filename.cbegin(), filename.cend(), std::back_inserter(fn), detail::toupper);
if(filename.size() >= 4)
auto dotpos = filename.find_last_of('.');
if (dotpos != filename.npos)
{
nana::string suffix = fn.substr(fn.size() - 4);
if(STR(".ICO") == suffix)
auto type_str = ::nana::cistring(filename.substr(dotpos + 1).data());
do
{
if (STR("ICO") == type_str)
{
#if defined(NANA_WINDOWS)
helper = new detail::image_ico(true);
helper = new detail::image_ico(true);
#else
return false;
#endif
}
break;
}
if (STR("PNG") == type_str)
{
#if defined(NANA_ENABLE_PNG)
else if(STR(".PNG") == suffix)
helper = new detail::image_png;
helper = new detail::image_png;
#else
return false;
#endif
break;
}
if (STR("JPG") == type_str || STR("JPEG") == type_str)
{
#if defined(NANA_ENABLE_JPEG)
helper = new detail::image_jpeg;
#else
return false;
#endif
break;
}
} while (false);
}
if(0 == helper)
//Check for BMP
if(!helper)
{
#if defined(NANA_UNICODE)
std::ifstream ifs(std::string(nana::charset(filename)).c_str(), std::ios::binary);

View File

@@ -611,6 +611,63 @@ namespace nana{ namespace paint
return reinterpret_cast<pixel_color_t*>(reinterpret_cast<char*>(sp->raw_pixel_buffer) + sp->bytes_per_line * row);
}
void pixel_buffer::fill_row(std::size_t row, const unsigned char* buffer, std::size_t bytes, unsigned bits_per_pixel)
{
auto sp = storage_.get();
if (!sp)
return;
auto row_ptr = sp->raw_pixel_buffer + sp->pixel_size.width * row;
//the number of pixels will be copied
auto const px_count = (sp->pixel_size.width <= (bytes / (bits_per_pixel / 8)) ? sp->pixel_size.width : (bytes / (bits_per_pixel / 8)));
if (32 == bits_per_pixel)
{
std::memcpy(row_ptr, buffer, px_count * 4);
}
else if (24 == bits_per_pixel)
{
for (auto p = row_ptr, end = row_ptr + px_count; p != end; ++p)
{
p->element.red = buffer[0];
p->element.green = buffer[1];
p->element.blue = buffer[2];
buffer += 3;
}
}
else if (16 == bits_per_pixel)
{
unsigned char palette[32];
for (std::size_t i = 0; i < 32; ++i)
palette[i] = static_cast<unsigned char>(i * 255 / 31);
#if defined(NANA_X11)
unsigned char palette_6bits[64];
for (std::size_t i = 0; i < 64; ++i)
palette_6bits[i] = static_cast<unsigned char>(i * 255 / 63);
#endif
auto px = reinterpret_cast<const unsigned short*>(buffer);
for (auto p = row_ptr, end = row_ptr + px_count; p != end; ++p)
{
p->element.red = palette[(*px >> 11) & 0x1F];
//16-bits RGB format under X is 565, under Windows is 555
#if defined(NANA_X11)
p->element.green = palette_6bits[(*px >> 5) & 0x3F];
p->element.blue = palette_[*px & 0x1F];
#else
p->element.green = palette[(*px >> 6) & 0x1F];
p->element.blue = palette[(*px >> 1) & 0x1F];
#endif
++px;
}
}
}
void pixel_buffer::put(const unsigned char* rawbits, std::size_t width, std::size_t height, std::size_t bits_per_pixel, std::size_t bytes_per_line, bool is_negative)
{
if(storage_)