egami
C++ Image Processing program
|
00001 #include <memory> 00002 #include <array> 00003 #include <algorithm> 00004 #include <string> 00005 #include <vector> 00006 00007 #include <gtkmm/image.h> 00008 #include <gtkmm/dialog.h> 00009 #include <gtkmm/spinbutton.h> 00010 #include <gtkmm/checkbutton.h> 00011 #include <gtkmm/label.h> 00012 #include <gtkmm/enums.h> 00013 #include <gtkmm/stock.h> 00014 00015 #include "../display_unit.hpp" 00016 #include "../processing_page.hpp" 00017 #include "../processing_unit.hpp" 00018 #include "../utils.hpp" 00019 #include "../progress.hpp" 00020 #include "order_statistic.hpp" 00021 00022 namespace{ 00023 class Config: public Gtk::Dialog { 00024 public: 00025 Config(): adj(Gtk::Adjustment::create(1, 1, 32, 1, 5)), tt("Precision:"), bt(adj), rb("Red"), gb("Green"), bb("Blue") { 00026 set_resizable(false); 00027 00028 rb.set_active(true); 00029 gb.set_active(true); 00030 bb.set_active(true); 00031 00032 get_vbox()->pack_start(tt); 00033 get_vbox()->pack_start(bt); 00034 get_vbox()->pack_start(rb); 00035 get_vbox()->pack_start(gb); 00036 get_vbox()->pack_start(bb); 00037 00038 add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK); 00039 add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); 00040 00041 show_all_children(); 00042 } 00043 00044 unsigned precision() const { 00045 return bt.get_value(); 00046 } 00047 00048 bool r_a() const { return rb.get_active(); } 00049 bool g_a() const { return gb.get_active(); } 00050 bool b_a() const { return bb.get_active(); } 00051 00052 private: 00053 Glib::RefPtr<Gtk::Adjustment> adj; 00054 Gtk::Label tt; 00055 Gtk::SpinButton bt; 00056 Gtk::CheckButton rb, gb, bb; 00057 }; 00058 00059 Display_unit *impl(const Image_unit *in){ 00060 Config config; 00061 if(config.run()!=Gtk::RESPONSE_OK) 00062 return nullptr; 00063 config.hide(); 00064 00065 std::vector<unsigned> red_norm(1+255/config.precision(), 0), green_norm(1+255/config.precision(), 0), blue_norm(1+255/config.precision(), 0); 00066 00067 for(auto pixel: *in){ 00068 red_norm[pixel.r/config.precision()]++; 00069 green_norm[pixel.g/config.precision()]++; 00070 blue_norm[pixel.b/config.precision()]++; 00071 } 00072 00073 std::array<unsigned, 256> red_hist{{}}, green_hist{{}}, blue_hist{{}}; 00074 unsigned max=1; 00075 for(unsigned short i=0; i<256; ++i){ 00076 if(config.r_a()) red_hist[i]=red_norm[i/config.precision()]; 00077 if(config.g_a()) green_hist[i]=green_norm[i/config.precision()]; 00078 if(config.b_a()) blue_hist[i]=blue_norm[i/config.precision()]; 00079 max=std::max(max, std::max(red_hist[i], std::max(green_hist[i], blue_hist[i]))); 00080 } 00081 00082 Image_unit *out(new Image_unit(in, 257, 258, false)); 00083 for(auto pixel: *out) 00084 pixel = {0}; 00085 00086 for(unsigned short i=0; i<256; ++i){ 00087 if(config.r_a()) 00088 for(unsigned j=0; j<red_hist[i]/static_cast<double>(max)*255; ++j) 00089 out->red(255-j, 1+i, 255); 00090 if(config.g_a()) 00091 for(unsigned j=0; j<green_hist[i]/static_cast<double>(max)*255; ++j) 00092 out->green(255-j, 1+i, 255); 00093 if(config.b_a()) 00094 for(unsigned j=0; j<blue_hist[i]/static_cast<double>(max)*255; ++j) 00095 out->blue(255-j, 1+i, 255); 00096 } 00097 return out; 00098 } 00099 } 00100 00101 namespace Processes{ 00102 void histogram(){ 00103 Gtk::Image icon(cmake_install_prefix+std::string("/share/egami/icons/histogram.png")); 00104 std::shared_ptr<Processing_unit> pu(new Processing_unit(Processing(&impl), "Histogram", icon, true)); 00105 Processing_page::add_unit_to_page("Colours", pu); 00106 } 00107 }