open png/jpg image with memory buffer
This commit is contained in:
		
							parent
							
								
									5a960ed88c
								
							
						
					
					
						commit
						3c8ee33ae8
					
				| @ -28,7 +28,7 @@ namespace paint | ||||
| 	public: | ||||
| 		class image_impl_interface; | ||||
| 
 | ||||
| 		image(); | ||||
| 		image() noexcept; | ||||
| 		image(const image&); | ||||
| 		image(image&&); | ||||
| 		explicit image(const ::std::string& file); | ||||
| @ -41,13 +41,13 @@ namespace paint | ||||
| 		bool open(const ::std::wstring& file); | ||||
| 		 | ||||
| 		/// Opens an icon from a specified buffer
 | ||||
| 		bool open_icon(const void* data, std::size_t bytes); | ||||
| 		bool empty() const; | ||||
| 		bool open(const void* data, std::size_t bytes); | ||||
| 		bool empty() const noexcept; | ||||
| 		operator unspecified_bool_t() const; | ||||
| 		void close(); | ||||
| 		void close() noexcept; | ||||
| 
 | ||||
| 		bool alpha() const; | ||||
| 		nana::size size() const; | ||||
| 		bool alpha() const noexcept; | ||||
| 		nana::size size() const noexcept; | ||||
| 		void paste(graphics& dst, const point& p_dst) const; | ||||
| 		void paste(const nana::rectangle& r_src, graphics& dst, const point& p_dst) const;///< Paste the area of picture specified by r_src into the destination graphics specified by dst at position p_dst.
 | ||||
| 		void stretch(const nana::rectangle& r_src, graphics& dst, const nana::rectangle& r_dst) const;///<Paste the picture into the dst, stretching or compressing the picture to fit the given area.
 | ||||
|  | ||||
| @ -13,10 +13,12 @@ | ||||
| #ifndef NANA_PAT_CLONEABLE_HPP | ||||
| #define NANA_PAT_CLONEABLE_HPP | ||||
| 
 | ||||
| #include <nana/c++defines.hpp> | ||||
| #include <cstddef> | ||||
| #include <type_traits> | ||||
| #include <memory> | ||||
| 
 | ||||
| 
 | ||||
| namespace nana{ namespace pat{ | ||||
| 
 | ||||
| 	namespace detail | ||||
| @ -99,9 +101,9 @@ namespace nana{ namespace pat{ | ||||
| 			: public std::enable_if<(!std::is_base_of<cloneable, typename std::remove_reference<U>::type>::value) && std::is_base_of<base_t, typename std::remove_reference<U>::type>::value, int> | ||||
| 		{}; | ||||
| 	public: | ||||
| 		cloneable() = default; | ||||
| 		cloneable() noexcept = default; | ||||
| 
 | ||||
| 		cloneable(std::nullptr_t){} | ||||
| 		cloneable(std::nullptr_t) noexcept{} | ||||
| 
 | ||||
| 		template<typename T, typename member_enabled<T>::type* = nullptr> | ||||
| 		cloneable(T&& t) | ||||
| @ -166,22 +168,22 @@ namespace nana{ namespace pat{ | ||||
| 			return *fast_ptr_; | ||||
| 		} | ||||
| 
 | ||||
| 		const_base_ref operator*() const | ||||
| 		const_base_ref operator*() const noexcept | ||||
| 		{ | ||||
| 			return *fast_ptr_; | ||||
| 		} | ||||
| 
 | ||||
| 		base_t * operator->() | ||||
| 		base_t * operator->() noexcept | ||||
| 		{ | ||||
| 			return fast_ptr_; | ||||
| 		} | ||||
| 
 | ||||
| 		const_base_ptr operator->() const | ||||
| 		const_base_ptr operator->() const noexcept | ||||
| 		{ | ||||
| 			return fast_ptr_; | ||||
| 		} | ||||
| 
 | ||||
| 		base_t * get() const | ||||
| 		base_t * get() const noexcept | ||||
| 		{ | ||||
| 			return fast_ptr_; | ||||
| 		} | ||||
| @ -192,7 +194,7 @@ namespace nana{ namespace pat{ | ||||
| 			cwrapper_.reset(); | ||||
| 		} | ||||
| 
 | ||||
| 		operator operator_bool_t() const volatile | ||||
| 		operator operator_bool_t() const volatile noexcept | ||||
| 		{ | ||||
| 			return (fast_ptr_ ? &inner_bool::true_stand : nullptr); | ||||
| 		} | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /*
 | ||||
|  *	A Thread Pool Implementation | ||||
|  *	Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) | ||||
|  *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) | ||||
|  * | ||||
|  *	Distributed under the Boost Software License, Version 1.0. | ||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
| #include <list> | ||||
| #include <map> | ||||
| #include <algorithm> | ||||
| #include <atomic> | ||||
| 
 | ||||
| #if defined(STD_THREAD_NOT_SUPPORTED) | ||||
|     #include <nana/std_thread.hpp> | ||||
| @ -350,7 +351,7 @@ namespace nana | ||||
| 		struct animation::impl | ||||
| 		{ | ||||
| 			bool	looped{false}; | ||||
| 			volatile bool	paused{true}; | ||||
| 			std::atomic<bool>	paused{true}; | ||||
| 			std::size_t fps; | ||||
| 
 | ||||
| 			std::list<frameset> framesets; | ||||
|  | ||||
| @ -25,6 +25,27 @@ namespace nana | ||||
| 				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 experimental::filesystem::path& jpeg_file) override | ||||
| 			{ | ||||
| @ -45,25 +66,10 @@ namespace nana | ||||
| 
 | ||||
| 					::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<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); | ||||
| 					} | ||||
| 					_m_read_jpg(jdstru); | ||||
| 
 | ||||
| 					jpeg_finish_decompress(&jdstru); | ||||
| 					is_opened = true; | ||||
| 				} | ||||
| 
 | ||||
| 				::jpeg_destroy_decompress(&jdstru); | ||||
| @ -73,8 +79,27 @@ namespace nana | ||||
| 
 | ||||
| 			bool open(const void* data, std::size_t bytes) override | ||||
| 			{ | ||||
| 				throw std::logic_error("JPEG is not supported for raw data buffer"); | ||||
| 				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_mem_src(&jdstru, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(data)), 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) | ||||
|  | ||||
| @ -19,6 +19,107 @@ namespace nana | ||||
| 		class image_png | ||||
| 			: public basic_image_pixbuf | ||||
| 		{ | ||||
| 			void _m_read_png(png_structp png_ptr, png_infop info_ptr) | ||||
| 			{ | ||||
| 				::png_read_info(png_ptr, info_ptr); | ||||
| 
 | ||||
| 				const int png_width = ::png_get_image_width(png_ptr, info_ptr); | ||||
| 				const int png_height = ::png_get_image_height(png_ptr, info_ptr); | ||||
| 				png_byte color_type = ::png_get_color_type(png_ptr, info_ptr); | ||||
| 				const auto bit_depth = ::png_get_bit_depth(png_ptr, info_ptr); | ||||
| 
 | ||||
| 				//do some extra work for palette/gray color type
 | ||||
| 				if (PNG_COLOR_TYPE_PALETTE == color_type) | ||||
| 					::png_set_palette_to_rgb(png_ptr); | ||||
| 				else if ((PNG_COLOR_TYPE_GRAY == color_type) && (bit_depth < 8)) | ||||
| 					::png_set_gray_to_rgb(png_ptr); | ||||
| 
 | ||||
| 				auto is_alpha_enabled = (::png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0); | ||||
| 				if (is_alpha_enabled) | ||||
| 					::png_set_tRNS_to_alpha(png_ptr); | ||||
| 
 | ||||
| 				//make sure 8-bit per channel
 | ||||
| 				if (16 == bit_depth) | ||||
| 					::png_set_strip_16(png_ptr); | ||||
| 
 | ||||
| 				::png_set_interlace_handling(png_ptr); | ||||
| 				::png_read_update_info(png_ptr, info_ptr); | ||||
| 
 | ||||
| 				//The following codes may longjmp while image_read error.
 | ||||
| 				png_bytep * row_ptrs = new png_bytep[png_height]; | ||||
| 				const std::size_t png_rowbytes = ::png_get_rowbytes(png_ptr, info_ptr); | ||||
| 
 | ||||
| 				pixbuf_.open(png_width, png_height); | ||||
| 
 | ||||
| 				is_alpha_enabled |= ((PNG_COLOR_MASK_ALPHA & color_type) != 0); | ||||
| 				pixbuf_.alpha_channel(is_alpha_enabled); | ||||
| 
 | ||||
| 				if (is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t))) | ||||
| 				{ | ||||
| 					for (int i = 0; i < png_height; ++i) | ||||
| 						row_ptrs[i] = reinterpret_cast<png_bytep>(pixbuf_.raw_ptr(i)); | ||||
| 
 | ||||
| 					::png_read_image(png_ptr, row_ptrs); | ||||
| 
 | ||||
| 					for (int i = 0; i < png_height; ++i) | ||||
| 					{ | ||||
| 						auto p = pixbuf_.raw_ptr(i); | ||||
| 						for (int u = 0; u < png_width; ++u) | ||||
| 						{ | ||||
| 							auto t = p[u].element.red; | ||||
| 							p[u].element.red = p[u].element.blue; | ||||
| 							p[u].element.blue = t; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					png_byte * png_pixbuf = new png_byte[png_height * png_rowbytes]; | ||||
| 
 | ||||
| 					for (int i = 0; i < png_height; ++i) | ||||
| 						row_ptrs[i] = reinterpret_cast<png_bytep>(png_pixbuf + png_rowbytes * i); | ||||
| 
 | ||||
| 					::png_read_image(png_ptr, row_ptrs); | ||||
| 					//::png_destroy_read_struct(&png_ptr, &info_ptr, 0);
 | ||||
| 
 | ||||
| 					std::size_t png_pixel_bytes = png_rowbytes / png_width; | ||||
| 
 | ||||
| 					pixel_argb_t * rgb_row_ptr = pixbuf_.raw_ptr(0); | ||||
| 					for (int y = 0; y < png_height; ++y) | ||||
| 					{ | ||||
| 						png_bytep png_ptr = row_ptrs[y]; | ||||
| 
 | ||||
| 						pixel_argb_t * rgb_end = rgb_row_ptr + png_width; | ||||
| 
 | ||||
| 						if (is_alpha_enabled) | ||||
| 						{ | ||||
| 							for (pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i) | ||||
| 							{ | ||||
| 								i->element.red = png_ptr[0]; | ||||
| 								i->element.green = png_ptr[1]; | ||||
| 								i->element.blue = png_ptr[2]; | ||||
| 								i->element.alpha_channel = png_ptr[3]; | ||||
| 								png_ptr += png_pixel_bytes; | ||||
| 							} | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							for (pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i) | ||||
| 							{ | ||||
| 								i->element.red = png_ptr[0]; | ||||
| 								i->element.green = png_ptr[1]; | ||||
| 								i->element.blue = png_ptr[2]; | ||||
| 								i->element.alpha_channel = 255; | ||||
| 								png_ptr += png_pixel_bytes; | ||||
| 							} | ||||
| 						} | ||||
| 						rgb_row_ptr = rgb_end; | ||||
| 					} | ||||
| 
 | ||||
| 					delete[] png_pixbuf; | ||||
| 				} | ||||
| 				delete[] row_ptrs; | ||||
| 			} | ||||
| 		public: | ||||
| 			bool open(const experimental::filesystem::path& png_file) override | ||||
| 			{ | ||||
| @ -44,109 +145,17 @@ namespace nana | ||||
| 							{ | ||||
| 								//The following codes may longjmp while init_io error.
 | ||||
| 								::png_init_io(png_ptr, fp); | ||||
| 
 | ||||
| 								//8-byte of sig has been read, tell the libpng there are some bytes missing from start of file
 | ||||
| 								::png_set_sig_bytes(png_ptr, 8); | ||||
| 								::png_read_info(png_ptr, info_ptr); | ||||
| 
 | ||||
| 								const int png_width = ::png_get_image_width(png_ptr, info_ptr); | ||||
| 								const int png_height = ::png_get_image_height(png_ptr, info_ptr); | ||||
| 								png_byte color_type = ::png_get_color_type(png_ptr, info_ptr); | ||||
| 								const auto bit_depth = ::png_get_bit_depth(png_ptr, info_ptr); | ||||
| 								_m_read_png(png_ptr, info_ptr); | ||||
| 
 | ||||
| 								//do some extra work for palette/gray color type
 | ||||
| 								if (PNG_COLOR_TYPE_PALETTE == color_type) | ||||
| 									::png_set_palette_to_rgb(png_ptr); | ||||
| 								else if ((PNG_COLOR_TYPE_GRAY == color_type) && (bit_depth < 8)) | ||||
| 									::png_set_gray_to_rgb(png_ptr); | ||||
| 
 | ||||
| 								bool is_alpha_enabled = (::png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0); | ||||
| 								if (is_alpha_enabled) | ||||
| 									::png_set_tRNS_to_alpha(png_ptr); | ||||
| 
 | ||||
| 								//make sure 8-bit per channel
 | ||||
| 								if (16 == bit_depth) | ||||
| 									::png_set_strip_16(png_ptr); | ||||
| 
 | ||||
| 								::png_set_interlace_handling(png_ptr); | ||||
| 								::png_read_update_info(png_ptr, info_ptr); | ||||
| 
 | ||||
| 								//The following codes may longjmp while image_read error.
 | ||||
| 								png_bytep * row_ptrs = new png_bytep[png_height]; | ||||
| 								const std::size_t png_rowbytes = ::png_get_rowbytes(png_ptr, info_ptr); | ||||
| 
 | ||||
| 								pixbuf_.open(png_width, png_height); | ||||
| 
 | ||||
| 								is_alpha_enabled |= ((PNG_COLOR_MASK_ALPHA & color_type) != 0); | ||||
| 								pixbuf_.alpha_channel(is_alpha_enabled); | ||||
| 
 | ||||
| 								if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t))) | ||||
| 								{ | ||||
| 									for(int i = 0; i < png_height; ++i) | ||||
| 										row_ptrs[i] = reinterpret_cast<png_bytep>(pixbuf_.raw_ptr(i)); | ||||
| 
 | ||||
| 									::png_read_image(png_ptr, row_ptrs); | ||||
| 									::png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); | ||||
| 
 | ||||
| 									for (int i = 0; i < png_height; ++i) | ||||
| 									{ | ||||
| 										auto p = pixbuf_.raw_ptr(i); | ||||
| 										for (int u = 0; u < png_width; ++u) | ||||
| 										{ | ||||
| 											auto t = p[u].element.red; | ||||
| 											p[u].element.red = p[u].element.blue; | ||||
| 											p[u].element.blue = t; | ||||
| 										} | ||||
| 									} | ||||
| 								} | ||||
| 								else | ||||
| 								{ | ||||
| 									png_byte * png_pixbuf = new png_byte[png_height * png_rowbytes]; | ||||
| 
 | ||||
| 									for(int i = 0; i < png_height; ++i) | ||||
| 										row_ptrs[i] = reinterpret_cast<png_bytep>(png_pixbuf + png_rowbytes * i); | ||||
| 
 | ||||
| 									::png_read_image(png_ptr, row_ptrs); | ||||
| 									::png_destroy_read_struct(&png_ptr, &info_ptr, 0); | ||||
| 
 | ||||
| 									std::size_t png_pixel_bytes = png_rowbytes / png_width; | ||||
| 
 | ||||
| 									pixel_argb_t * rgb_row_ptr = pixbuf_.raw_ptr(0); | ||||
| 									for(int y = 0; y < png_height; ++y) | ||||
| 									{ | ||||
| 										png_bytep png_ptr = row_ptrs[y]; | ||||
| 
 | ||||
| 										pixel_argb_t * rgb_end = rgb_row_ptr + png_width; | ||||
| 
 | ||||
| 										if(is_alpha_enabled) | ||||
| 										{ | ||||
| 											for(pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i) | ||||
| 											{ | ||||
| 												i->element.red = png_ptr[0]; | ||||
| 												i->element.green = png_ptr[1]; | ||||
| 												i->element.blue = png_ptr[2]; | ||||
| 												i->element.alpha_channel = png_ptr[3]; | ||||
| 												png_ptr += png_pixel_bytes; | ||||
| 											} | ||||
| 										} | ||||
| 										else | ||||
| 										{ | ||||
| 											for(pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i) | ||||
| 											{ | ||||
| 												i->element.red = png_ptr[0]; | ||||
| 												i->element.green = png_ptr[1]; | ||||
| 												i->element.blue = png_ptr[2]; | ||||
| 												i->element.alpha_channel = 255; | ||||
| 												png_ptr += png_pixel_bytes; | ||||
| 											} | ||||
| 										} | ||||
| 										rgb_row_ptr = rgb_end; | ||||
| 									} | ||||
| 
 | ||||
| 									delete [] png_pixbuf; | ||||
| 								} | ||||
| 								delete [] row_ptrs; | ||||
| 								is_opened = true; | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						::png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| @ -154,10 +163,60 @@ namespace nana | ||||
| 				return is_opened; | ||||
| 			} | ||||
| 
 | ||||
| 			class png_reader | ||||
| 			{ | ||||
| 			public: | ||||
| 				png_reader(const void* data, std::size_t bytes) noexcept | ||||
| 					: data_ptr_(reinterpret_cast<const char*>(data)), bytes_(bytes) | ||||
| 				{ | ||||
| 				} | ||||
| 
 | ||||
| 				static void PNGCAPI read(png_structp png_ptr, png_bytep buf, png_size_t bytes) | ||||
| 				{ | ||||
| 					auto self = reinterpret_cast<png_reader*>(::png_get_io_ptr(png_ptr)); | ||||
| 
 | ||||
| 					auto read_bytes = self->bytes_ < bytes ? self->bytes_ : bytes; | ||||
| 
 | ||||
| 					if (read_bytes) | ||||
| 						std::memcpy(buf, self->data_ptr_, read_bytes); | ||||
| 
 | ||||
| 					self->bytes_ -= read_bytes; | ||||
| 					self->data_ptr_ += read_bytes; | ||||
| 				} | ||||
| 			private: | ||||
| 				const char* data_ptr_; | ||||
| 				std::size_t bytes_; | ||||
| 			}; | ||||
| 
 | ||||
| 			bool open(const void* data, std::size_t bytes) override | ||||
| 			{ | ||||
| 				throw std::logic_error("PNG is not supported for raw data buffer"); | ||||
| 				return false; | ||||
| 				if (bytes < 8 || 0 != ::png_sig_cmp(reinterpret_cast<png_const_bytep>(data), 0, 8)) | ||||
| 					return false; | ||||
| 
 | ||||
| 				auto png_ptr = ::png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); | ||||
| 				if (!png_ptr) | ||||
| 					return false; | ||||
| 				 | ||||
| 				bool is_opened = false; | ||||
| 
 | ||||
| 				png_infop info_ptr = ::png_create_info_struct(png_ptr); | ||||
| 
 | ||||
| 				if (info_ptr) | ||||
| 				{ | ||||
| 					png_reader reader{ data, bytes }; | ||||
| 
 | ||||
| 					if (!setjmp(png_jmpbuf(png_ptr))) | ||||
| 					{ | ||||
| 						::png_set_read_fn(png_ptr, &reader, &png_reader::read); | ||||
| 
 | ||||
| 						_m_read_png(png_ptr, info_ptr); | ||||
| 						is_opened = true; | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				::png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); | ||||
| 				 | ||||
| 				return is_opened; | ||||
| 			} | ||||
| 		}; | ||||
| 	}//end namespace detail
 | ||||
|  | ||||
| @ -163,7 +163,7 @@ namespace paint | ||||
| 	{} | ||||
| 
 | ||||
| 	//class image
 | ||||
| 		image::image() | ||||
| 		image::image() noexcept | ||||
| 		{} | ||||
| 
 | ||||
| 		image::image(const image& rhs) | ||||
| @ -245,7 +245,7 @@ namespace paint | ||||
| 				if (ext_png == ext) | ||||
| 				{ | ||||
| #if defined(NANA_ENABLE_PNG) | ||||
| 					ptr = std::make_shared<detail::image_png>; | ||||
| 					ptr = std::make_shared<detail::image_png>(); | ||||
| #else | ||||
| 					return ptr; | ||||
| #endif | ||||
| @ -299,14 +299,53 @@ namespace paint | ||||
| 			return (image_ptr_ ? image_ptr_->open(path) : false); | ||||
| 		} | ||||
| 
 | ||||
| 		bool image::open_icon(const void* data, std::size_t bytes) | ||||
| 		bool image::open(const void* data, std::size_t bytes) | ||||
| 		{ | ||||
| 			image::image_impl_interface * helper = new detail::image_ico(true); | ||||
| 			image_ptr_ = std::shared_ptr<image_impl_interface>(helper); | ||||
| 			return helper->open(data, bytes); | ||||
| 			close(); | ||||
| 
 | ||||
| 			if (bytes > 2) | ||||
| 			{ | ||||
| 				std::shared_ptr<image::image_impl_interface> ptr; | ||||
| 
 | ||||
| 				auto meta = *reinterpret_cast<const unsigned short*>(data); | ||||
| 				 | ||||
| 				if (*reinterpret_cast<const short*>("BM") == meta) | ||||
| 					ptr = std::make_shared<detail::image_bmp>(); | ||||
| 				else if (*reinterpret_cast<const short*>("MZ") == meta) | ||||
| 					ptr = std::make_shared<detail::image_ico>(false); | ||||
| 				else | ||||
| 				{ | ||||
| 					if (bytes > 8 && (0x474e5089 == *reinterpret_cast<const unsigned*>(data))) | ||||
| 					{ | ||||
| #if defined(NANA_ENABLE_PNG) | ||||
| 						ptr = std::make_shared<detail::image_png>(); | ||||
| #endif | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| #if defined(NANA_ENABLE_JPEG) | ||||
| 						//JFIF
 | ||||
| 						if (bytes > 11 && (0xe0ffd8ff == *reinterpret_cast<const unsigned*>(data)) && 0x4649464A == *reinterpret_cast<const unsigned*>(reinterpret_cast<const char*>(data)+6)) | ||||
| 							ptr = std::make_shared<detail::image_jpeg>(); | ||||
| 						else if (bytes > 9 && (0x66697845 == *reinterpret_cast<const unsigned*>(reinterpret_cast<const char*>(data)+5))) //Exif
 | ||||
| 							ptr = std::make_shared<detail::image_jpeg>(); | ||||
| #endif | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 
 | ||||
| 				if (ptr) | ||||
| 				{ | ||||
| 					image_ptr_.swap(ptr); | ||||
| 					return image_ptr_->open(data, bytes); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		bool image::empty() const | ||||
| 
 | ||||
| 		bool image::empty() const noexcept | ||||
| 		{ | ||||
| 			return ((nullptr == image_ptr_) || image_ptr_->empty()); | ||||
| 		} | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /*
 | ||||
|  *	A Thread Pool Implementation | ||||
|  *	Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) | ||||
|  *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) | ||||
|  * | ||||
|  *	Distributed under the Boost Software License, Version 1.0. | ||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||
| @ -15,6 +15,7 @@ | ||||
| #include <time.h> | ||||
| #include <deque> | ||||
| #include <vector> | ||||
| #include <atomic> | ||||
| 
 | ||||
| #if defined(STD_THREAD_NOT_SUPPORTED) | ||||
|     #include <nana/std_mutex.hpp> | ||||
| @ -62,23 +63,22 @@ namespace threads | ||||
| 			{ | ||||
| #if defined(NANA_WINDOWS) | ||||
| 				typedef HANDLE thread_t; | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 				typedef pthread_t thread_t; | ||||
| #endif | ||||
| 				impl * pool_ptr; | ||||
| 				task * task_ptr; | ||||
| 				thread_t	handle; | ||||
| 				volatile state	thr_state; | ||||
| 				std::atomic<state>	thr_state; | ||||
| 				time_t	timestamp; | ||||
| #if defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #if defined(NANA_POSIX) | ||||
| 				std::mutex wait_mutex; | ||||
| 				std::condition_variable wait_cond; | ||||
| 				volatile bool suspended; | ||||
| 				std::atomic<bool> suspended; | ||||
| #endif | ||||
| 			}; | ||||
| 		public: | ||||
| 			impl(std::size_t thr_number) | ||||
| 				: runflag_(true) | ||||
| 			{ | ||||
| 				if(0 == thr_number) thr_number = 4; | ||||
| 
 | ||||
| @ -90,7 +90,7 @@ namespace threads | ||||
| 					pto->task_ptr = nullptr; | ||||
| #if defined(NANA_WINDOWS) | ||||
| 					pto->handle = (HANDLE)::_beginthreadex(0, 0, reinterpret_cast<unsigned(__stdcall*)(void*)>(&impl::_m_thr_starter), pto, 0, 0); | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 					pto->suspended = false; | ||||
| 					::pthread_create(&(pto->handle), 0, reinterpret_cast<void*(*)(void*)>(&impl::_m_thr_starter), pto); | ||||
| #endif | ||||
| @ -137,7 +137,7 @@ namespace threads | ||||
| #if defined(NANA_WINDOWS) | ||||
| 					::WaitForSingleObject(thr->handle, INFINITE); | ||||
| 					::CloseHandle(thr->handle); | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 					::pthread_join(thr->handle, 0); | ||||
| 					::pthread_detach(thr->handle); | ||||
| #endif | ||||
| @ -223,7 +223,7 @@ namespace threads | ||||
| 				pto->thr_state = state::idle; | ||||
| #if defined(NANA_WINDOWS) | ||||
| 				::SuspendThread(pto->handle); | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 				std::unique_lock<std::mutex> lock(pto->wait_mutex); | ||||
| 				pto->suspended = true; | ||||
| 				pto->wait_cond.wait(lock); | ||||
| @ -240,7 +240,7 @@ namespace threads | ||||
| 					if(n == 1 || n == static_cast<DWORD>(-1)) | ||||
| 						break; | ||||
| 				} | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 				while(false == pto->suspended) | ||||
| 					; | ||||
| 				std::unique_lock<std::mutex> lock(pto->wait_mutex); | ||||
| @ -327,7 +327,7 @@ namespace threads | ||||
| 				::_endthreadex(0); | ||||
| 				return 0; | ||||
| 			} | ||||
| #elif defined(NANA_LINUX) || defined(NANA_MACOS) | ||||
| #elif defined(NANA_POSIX) | ||||
| 			static void * _m_thr_starter(pool_throbj * pto) | ||||
| 			{ | ||||
| 				pto->pool_ptr->_m_thr_runner(pto); | ||||
| @ -335,7 +335,7 @@ namespace threads | ||||
| 			} | ||||
| #endif | ||||
| 		private: | ||||
| 			volatile bool runflag_; | ||||
| 			std::atomic<bool> runflag_{ true }; | ||||
| 			std::recursive_mutex mutex_; | ||||
| 
 | ||||
| 			struct signal | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinhao
						Jinhao