From 23ed98693238c29d59962aa529fcdc35f6e8de3e Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 17 Oct 2015 14:46:02 +0800 Subject: [PATCH] add support of JPEG by using libjpeg --- include/nana/config.hpp | 8 +++ source/paint/detail/image_jpeg.hpp | 95 ++++++++++++++++++++++++++++++ source/paint/image.cpp | 3 + 3 files changed, 106 insertions(+) create mode 100644 source/paint/detail/image_jpeg.hpp diff --git a/include/nana/config.hpp b/include/nana/config.hpp index 9e0a2df7..d1dfef77 100644 --- a/include/nana/config.hpp +++ b/include/nana/config.hpp @@ -87,6 +87,14 @@ #define NANA_LIBPNG //Comment it to use libpng from operating system. #endif +/////////////////// +//Support for JPEG +// Define the NANA_ENABLE_JPEG to enable the support of JPEG. +// +//#define NANA_ENABLE_JPEG //! +#if defined(NANA_ENABLE_JPEG) + #define NANA_LIBJPEG //Comment this whole line to use libjpeg from operating system. +#endif #endif //NANA_CONFIG_HPP diff --git a/source/paint/detail/image_jpeg.hpp b/source/paint/detail/image_jpeg.hpp new file mode 100644 index 00000000..d0ad9f8b --- /dev/null +++ b/source/paint/detail/image_jpeg.hpp @@ -0,0 +1,95 @@ +#ifndef NANA_PAINT_DETAIL_IMAGE_JPEG_HPP +#define NANA_PAINT_DETAIL_IMAGE_JPEG_HPP + +#include "image_pixbuf.hpp" + +//Separate the libpng from the package that system provides. +#if defined(NANA_LIBJPEG) + #include +#else + #include +#endif + +#include + +namespace nana +{ + namespace paint{ namespace detail{ + + class image_jpeg + : public basic_image_pixbuf + { + struct error_mgr + { + struct ::jpeg_error_mgr pub; + jmp_buf setjmp_buf; + }; + public: + bool open(const nana::char_t* jpeg_file) override + { +#ifdef NANA_UNICODE + FILE * fp = ::fopen(static_cast(nana::charset(jpeg_file)).c_str(), "rb"); +#else + FILE* fp = ::fopen(jpeg_file, "rb"); +#endif + if(nullptr == fp) return false; + + bool is_opened = false; + + struct ::jpeg_decompress_struct jdstru; + error_mgr jerr; + + jdstru.err = ::jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = _m_error_handler; + + if (!setjmp(jerr.setjmp_buf)) + { + ::jpeg_create_decompress(&jdstru); + + ::jpeg_stdio_src(&jdstru, fp); + + ::jpeg_read_header(&jdstru, true); //Reject a tables-only JPEG file as an error + + ::jpeg_start_decompress(&jdstru); + + //JSAMPLEs per row in output buffer + auto row_stride = jdstru.output_width * jdstru.output_components; + + pixbuf_.open(jdstru.output_width, jdstru.output_height); + + auto row_buf = jdstru.mem->alloc_sarray(reinterpret_cast(&jdstru), JPOOL_IMAGE, row_stride, 1); + + while (jdstru.output_scanline < jdstru.output_height) + { + ::jpeg_read_scanlines(&jdstru, row_buf, 1); + + pixbuf_.fill_row(jdstru.output_scanline - 1, reinterpret_cast(*row_buf), row_stride, jdstru.output_components * 8); + } + + jpeg_finish_decompress(&jdstru); + } + + ::jpeg_destroy_decompress(&jdstru); + ::fclose(fp); + return is_opened; + } + + bool open(const void* data, std::size_t bytes) override + { + throw std::logic_error("JPEG is not supported for raw data buffer"); + return false; + } + private: + static void _m_error_handler(::j_common_ptr jdstru) + { + auto err_ptr = reinterpret_cast(jdstru->err); + + err_ptr->pub.output_message(jdstru); + longjmp(err_ptr->setjmp_buf, 1); + } + }; + }//end namespace detail + }//end namespace paint +}//end namespace nana + +#endif diff --git a/source/paint/image.cpp b/source/paint/image.cpp index 144bb2e9..c8a4098e 100644 --- a/source/paint/image.cpp +++ b/source/paint/image.cpp @@ -21,6 +21,9 @@ #include #include +#if defined(NANA_ENABLE_JPEG) +#include "detail/image_jpeg.hpp" +#endif #if defined(NANA_ENABLE_PNG) #include "detail/image_png.hpp"