improve image and pixel_buffer
This commit is contained in:
@@ -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
|
||||
|
||||
63
source/paint/detail/image_pixbuf.hpp
Normal file
63
source/paint/detail/image_pixbuf.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_)
|
||||
|
||||
Reference in New Issue
Block a user