118 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #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 <nana_extrlib/jpeglib.h>
 | |
| #else
 | |
| 	#include <jpeglib.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <csetjmp>
 | |
| 
 | |
| namespace nana
 | |
| {
 | |
| 	namespace paint{	namespace detail{
 | |
| 
 | |
| 		class image_jpeg
 | |
| 			: public basic_image_pixbuf
 | |
| 		{
 | |
| 			struct error_mgr
 | |
| 			{
 | |
| 				struct ::jpeg_error_mgr pub;
 | |
| 				std::jmp_buf	setjmp_buf;
 | |
| 			};
 | |
| 
 | |
| 			void _m_read_jpg(jpeg_decompress_struct& jdstru)
 | |
| 			{
 | |
| 				::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<j_common_ptr>(&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<unsigned char*>(*row_buf), row_stride, jdstru.output_components * 8);
 | |
| 				}
 | |
| 			}
 | |
| 		public:
 | |
| 			bool open(const std::filesystem::path& jpeg_file) override
 | |
| 			{
 | |
| 				auto fp = ::fopen(to_osmbstr(to_utf8(jpeg_file.native())).c_str(), "rb");
 | |
| 				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);
 | |
| 
 | |
| 					_m_read_jpg(jdstru);
 | |
| 
 | |
| 					jpeg_finish_decompress(&jdstru);
 | |
| 					is_opened = true;
 | |
| 				}
 | |
| 
 | |
| 				::jpeg_destroy_decompress(&jdstru);
 | |
| 				::fclose(fp);
 | |
| 				return is_opened;
 | |
| 			}
 | |
| 
 | |
| 			bool open(const void* data, std::size_t bytes) override
 | |
| 			{
 | |
| 				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_mem_src(&jdstru, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(data)), static_cast<unsigned long>(bytes));
 | |
| 					_m_read_jpg(jdstru);
 | |
| 
 | |
| 					jpeg_finish_decompress(&jdstru);
 | |
| 					is_opened = true;
 | |
| 				}
 | |
| 
 | |
| 				::jpeg_destroy_decompress(&jdstru);
 | |
| 				return is_opened;
 | |
| 			}
 | |
| 		private:
 | |
| 			static void _m_error_handler(::j_common_ptr jdstru)
 | |
| 			{
 | |
| 				auto err_ptr = reinterpret_cast<error_mgr*>(jdstru->err);
 | |
| 
 | |
| 				err_ptr->pub.output_message(jdstru);
 | |
| 				longjmp(err_ptr->setjmp_buf, 1);
 | |
| 			}
 | |
| 		};
 | |
| 	}//end namespace detail
 | |
| 	}//end namespace paint
 | |
| }//end namespace nana
 | |
| 
 | |
| #endif
 | 
