Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * color_train_widget.cpp - Color training widget 00004 * 00005 * Created: Thu Mar 20 22:19:36 2008 00006 * Copyright 2008 Daniel Beck 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include <tools/firestation/color_train_widget.h> 00024 #include <tools/firestation/colormap_viewer_widget.h> 00025 #include <fvutils/color/yuv.h> 00026 #include <fvutils/color/zauberstab.h> 00027 #include <fvutils/color/colorspaces.h> 00028 #include <fvutils/color/conversions.h> 00029 #include <fvutils/draw/drawer.h> 00030 #include <fvutils/scalers/lossy.h> 00031 #include <fvutils/colormap/bayes/bayes_generator.h> 00032 #include <fvutils/colormap/yuvcm.h> 00033 #include <fvutils/colormap/cmfile.h> 00034 00035 #include <fvutils/writers/jpeg.h> 00036 00037 #include <fvutils/color/color_object_map.h> 00038 00039 #include <core/exceptions/software.h> 00040 00041 using namespace firevision; 00042 00043 /** @class ColorTrainWidget "color_train_widget.h" 00044 * This widget implements the complete color training process. 00045 * 00046 * @author Daniel Beck 00047 */ 00048 00049 /** Constructor. 00050 * @param parent the parent window 00051 */ 00052 ColorTrainWidget::ColorTrainWidget(Gtk::Window* parent) 00053 { 00054 m_generator = 0; 00055 m_zauberstab = new Zauberstab(); 00056 m_cvw = new ColormapViewerWidget(); 00057 00058 m_src_buffer = 0; 00059 m_draw_buffer = 0; 00060 00061 m_wnd_parent = parent; 00062 m_btn_reset_selection = 0; 00063 m_btn_add_to_colormap = 0; 00064 m_btn_reset_colormap = 0; 00065 m_btn_load_histos = 0; 00066 m_btn_save_histos = 0; 00067 m_btn_load_colormap = 0; 00068 m_btn_save_colormap = 0; 00069 m_spbtn_cm_depth = 0; 00070 m_spbtn_cm_width = 0; 00071 m_spbtn_cm_height = 0; 00072 m_img_segmentation = 0; 00073 m_scl_threshold = 0; 00074 m_scl_min_prob = 0; 00075 m_fcd_filechooser = 0; 00076 } 00077 00078 /** Destructor. */ 00079 ColorTrainWidget::~ColorTrainWidget() 00080 { 00081 delete m_cvw; 00082 delete m_generator; 00083 delete m_zauberstab; 00084 } 00085 00086 /** Set the current foreground object. 00087 * @param fg_object the foreground object 00088 */ 00089 void 00090 ColorTrainWidget::set_fg_object(hint_t fg_object) 00091 { 00092 m_fg_object = fg_object; 00093 } 00094 00095 /** Set the buffer containing the image data. 00096 * @param yuv422_buffer the YUV422_PLANAR buffer holding the image data 00097 * @param img_width the width of the image 00098 * @param img_height the height of the image 00099 */ 00100 void 00101 ColorTrainWidget::set_src_buffer(unsigned char* yuv422_buffer, 00102 unsigned int img_width, unsigned int img_height) 00103 { 00104 m_img_width = img_width; 00105 m_img_height = img_height; 00106 m_src_buffer = yuv422_buffer; 00107 m_img_cs = YUV422_PLANAR; 00108 m_img_size = colorspace_buffer_size( m_img_cs, m_img_width, m_img_height ); 00109 00110 if (yuv422_buffer) 00111 { 00112 m_zauberstab->deleteRegion(); 00113 m_zauberstab->setBuffer(m_src_buffer, m_img_width, m_img_height); 00114 m_zauberstab->setThreshold(10); 00115 } 00116 else 00117 { 00118 m_img_segmentation->clear(); 00119 m_img_segmentation->set("gtk-missing-image"); 00120 } 00121 } 00122 00123 /** Set the buffer to draw the selection into. 00124 * It is assumed that this buffer has the same dimensions as the buffer holding 00125 * the soruce image. 00126 * @param buffer the draw buffer 00127 */ 00128 void 00129 ColorTrainWidget::set_draw_buffer(unsigned char* buffer) 00130 { 00131 m_draw_buffer = buffer; 00132 } 00133 00134 /** The user clicked into the image. 00135 * @param x the x-coordinate 00136 * @param y the y-coordinate 00137 * @param button 1 for left click, 3 for right click @see GdkEventButton 00138 */ 00139 void 00140 ColorTrainWidget::click(unsigned int x, unsigned int y, unsigned int button) 00141 { 00142 if (m_src_buffer == 0 || m_draw_buffer == 0) 00143 { return; } 00144 00145 if ( m_zauberstab->isEmptyRegion() ) 00146 { 00147 if (button == MOUSE_BUTTON_LEFT) //left click 00148 { 00149 m_zauberstab->findRegion(x, y); 00150 } 00151 } 00152 else 00153 { 00154 if (button == MOUSE_BUTTON_LEFT) //left click 00155 { 00156 m_zauberstab->addRegion(x, y); 00157 } 00158 00159 if (button == MOUSE_BUTTON_RIGHT) //right click 00160 { 00161 m_zauberstab->deleteRegion(x, y); 00162 } 00163 } 00164 00165 memcpy(m_draw_buffer, m_src_buffer, m_img_size); 00166 00167 ZRegion *region = m_zauberstab->getRegion(); 00168 Drawer *d = new Drawer(); 00169 d->set_buffer( m_draw_buffer, m_img_width, m_img_height ); 00170 00171 for (unsigned int s = 0; s < region->slices->size(); s++) 00172 { 00173 d->draw_rectangle_inverted( region->slices->at(s)->leftX, 00174 region->slices->at(s)->y, 00175 region->slices->at(s)->rightX - region->slices->at(s)->leftX, 00176 1 ); 00177 } 00178 00179 delete d; 00180 00181 m_signal_update_image(); 00182 } 00183 00184 /** Reset the selection. */ 00185 void 00186 ColorTrainWidget::reset_selection() 00187 { 00188 if (m_zauberstab) 00189 { m_zauberstab->deleteRegion(); } 00190 00191 if( m_src_buffer && m_draw_buffer ) 00192 { memcpy(m_draw_buffer, m_src_buffer, m_img_size); } 00193 00194 m_signal_update_image(); 00195 } 00196 00197 /** Set the button to reset the selection. 00198 * @param btn the reset selection button 00199 */ 00200 void 00201 ColorTrainWidget::set_reset_selection_btn(Gtk::Button* btn) 00202 { 00203 m_btn_reset_selection = btn; 00204 m_btn_reset_selection->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::reset_selection) ); 00205 } 00206 00207 /** Set the button to trigger the generation of the colormap. 00208 * @param btn a Button 00209 */ 00210 void 00211 ColorTrainWidget::set_add_to_colormap_btn(Gtk::Button* btn) 00212 { 00213 m_btn_add_to_colormap = btn; 00214 m_btn_add_to_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::add_to_colormap) ); 00215 } 00216 00217 /** Set the button to reset the colormap. 00218 * @param btn a Button 00219 */ 00220 void 00221 ColorTrainWidget::set_reset_colormap_btn(Gtk::Button* btn) 00222 { 00223 m_btn_reset_colormap = btn; 00224 m_btn_reset_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::reset_colormap) ); 00225 } 00226 00227 /** Set the buffon to open a dialog to load histograms. 00228 * @param btn a Button 00229 */ 00230 void 00231 ColorTrainWidget::set_load_histos_btn(Gtk::Button* btn) 00232 { 00233 m_btn_load_histos = btn; 00234 m_btn_load_histos->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::load_histograms) ); 00235 } 00236 00237 /** Set the buffon to open a dialog to save histograms. 00238 * @param btn a Button 00239 */ 00240 void 00241 ColorTrainWidget::set_save_histos_btn(Gtk::Button* btn) 00242 { 00243 m_btn_save_histos = btn; 00244 m_btn_save_histos->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::save_histograms) ); 00245 } 00246 00247 /** Set the buffon to open a dialog to load a colormap. 00248 * @param btn a Button 00249 */ 00250 void 00251 ColorTrainWidget::set_load_colormap_btn(Gtk::Button* btn) 00252 { 00253 m_btn_load_colormap = btn; 00254 m_btn_load_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::load_colormap) ); 00255 } 00256 00257 /** Set the buffon to open a dialog to save a colormap. 00258 * @param btn a Button 00259 */ 00260 void 00261 ColorTrainWidget::set_save_colormap_btn(Gtk::Button* btn) 00262 { 00263 m_btn_save_colormap = btn; 00264 m_btn_save_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::save_colormap) ); 00265 } 00266 00267 /** Set the image to render the colormap into. 00268 * @param img an Image 00269 */ 00270 void 00271 ColorTrainWidget::set_colormap_img(Gtk::Image* img) 00272 { 00273 m_cvw->set_colormap_img(img); 00274 } 00275 00276 /** Set the image to render the segmented image into. 00277 * @param img an Image 00278 */ 00279 void 00280 ColorTrainWidget::set_segmentation_img(Gtk::Image* img) 00281 { 00282 m_img_segmentation = img; 00283 m_seg_img_max_width = m_img_segmentation->get_width(); 00284 m_seg_img_max_height = m_img_segmentation->get_height(); 00285 m_img_segmentation->signal_size_allocate().connect( sigc::mem_fun( *this, &ColorTrainWidget::resize_seg_image) ); 00286 } 00287 00288 void 00289 ColorTrainWidget::resize_seg_image(Gtk::Allocation& allocation) 00290 { 00291 unsigned int new_width = (unsigned int) allocation.get_width(); 00292 unsigned int new_height = (unsigned int) allocation.get_height(); 00293 00294 if (new_width != m_seg_img_max_width || new_height != m_seg_img_max_height) 00295 { 00296 m_seg_img_max_width = new_width; 00297 m_seg_img_max_height = new_height; 00298 draw_segmentation_result(); 00299 } 00300 } 00301 00302 /** Set the scale to control the selection threshold. 00303 * @param scl a Scale 00304 */ 00305 void 00306 ColorTrainWidget::set_threshold_scl(Gtk::Scale* scl) 00307 { 00308 m_scl_threshold = scl; 00309 m_scl_threshold->signal_change_value().connect( sigc::mem_fun(*this, &ColorTrainWidget::set_threshold) ); 00310 } 00311 00312 /** Set the scale to control the minimum probability. 00313 * @param scl a Scale 00314 */ 00315 void 00316 ColorTrainWidget::set_min_prob_scl(Gtk::Scale* scl) 00317 { 00318 m_scl_min_prob = scl; 00319 m_scl_min_prob->signal_change_value().connect( sigc::mem_fun(*this, &ColorTrainWidget::set_min_prob) ); 00320 } 00321 00322 /** Set the filechooser dialog to be used by this widget. 00323 * @param dlg a FileChooserDialog 00324 */ 00325 void 00326 ColorTrainWidget::set_filechooser_dlg(Gtk::FileChooserDialog* dlg) 00327 { 00328 m_fcd_filechooser = dlg; 00329 } 00330 00331 /** Set the widget to choose the layer of the colormap to display. 00332 * @param scl a Scale 00333 */ 00334 void 00335 ColorTrainWidget::set_cm_layer_selector(Gtk::Scale* scl) 00336 { 00337 m_cvw->set_layer_selector(scl); 00338 } 00339 00340 /** Set the widget to adjust the depth of the colormap. 00341 * @param depth SpinButton to set the Y-resolution of the color map 00342 * @param width SpinButton to set the U-resolution of the color map 00343 * @param height SpinButton to set the V-resolution of the color map 00344 */ 00345 void 00346 ColorTrainWidget::set_cm_selector(Gtk::SpinButton* depth, Gtk::SpinButton* width, Gtk::SpinButton* height) 00347 { 00348 m_spbtn_cm_depth = depth; 00349 m_spbtn_cm_width = width; 00350 m_spbtn_cm_height = height; 00351 } 00352 00353 /** Access the signal that is emitted whenever a redraw of the image is necessary. 00354 * @return reference to a Dispatcher. 00355 */ 00356 Glib::Dispatcher& 00357 ColorTrainWidget::update_image() 00358 { 00359 return m_signal_update_image; 00360 } 00361 00362 /** Access the signal that is emitted whenever the colormap has changed. 00363 * @return reference to a Dispatcher. 00364 */ 00365 Glib::Dispatcher& 00366 ColorTrainWidget::colormap_updated() 00367 { 00368 return m_signal_colormap_updated; 00369 } 00370 00371 /** Open a dialog to load a histogram. */ 00372 void 00373 ColorTrainWidget::load_histograms() 00374 { 00375 if ( !m_fcd_filechooser ) 00376 { return; } 00377 00378 m_fcd_filechooser->set_title("Load histograms"); 00379 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN); 00380 00381 m_fcd_filechooser->set_transient_for(*m_wnd_parent); 00382 00383 int result = m_fcd_filechooser->run(); 00384 00385 switch(result) 00386 { 00387 case (Gtk::RESPONSE_OK): 00388 { 00389 std::string filename = m_fcd_filechooser->get_filename(); 00390 if (!m_generator) 00391 { m_generator = new BayesColormapGenerator(); } 00392 m_generator->load_histograms( filename.c_str() ); 00393 m_generator->calc(); 00394 m_signal_colormap_updated(); 00395 00396 YuvColormap *cur = m_generator->get_current(); 00397 if (m_spbtn_cm_depth) m_spbtn_cm_depth->set_value(log(cur->depth()) / log(2)); 00398 if (m_spbtn_cm_width) m_spbtn_cm_width->set_value(log(cur->width()) / log(2)); 00399 if (m_spbtn_cm_height) m_spbtn_cm_height->set_value(log(cur->height()) / log(2)); 00400 00401 m_cvw->set_colormap(cur); 00402 m_cvw->draw(); 00403 draw_segmentation_result(); 00404 break; 00405 } 00406 00407 case (Gtk::RESPONSE_CANCEL): 00408 break; 00409 00410 default: 00411 break; 00412 } 00413 00414 m_fcd_filechooser->hide(); 00415 } 00416 00417 /** Open a dialog to save a histogram. */ 00418 void 00419 ColorTrainWidget::save_histograms() 00420 { 00421 if ( !m_fcd_filechooser ) 00422 { return; } 00423 00424 m_fcd_filechooser->set_title("Save histograms"); 00425 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_SAVE); 00426 00427 m_fcd_filechooser->set_transient_for(*m_wnd_parent); 00428 00429 int result = m_fcd_filechooser->run(); 00430 00431 switch(result) 00432 { 00433 case (Gtk::RESPONSE_OK): 00434 { 00435 std::string filename = m_fcd_filechooser->get_filename(); 00436 m_generator->save_histograms( filename.c_str() ); 00437 break; 00438 } 00439 00440 case (Gtk::RESPONSE_CANCEL): 00441 break; 00442 00443 default: 00444 break; 00445 } 00446 00447 m_fcd_filechooser->hide(); 00448 } 00449 00450 /** Generate a new colormap by adding the current histograms. */ 00451 void 00452 ColorTrainWidget::add_to_colormap() 00453 { 00454 if ( !m_src_buffer ) 00455 { return; } 00456 00457 unsigned int cm_depth; 00458 if (m_spbtn_cm_depth) 00459 { cm_depth = (unsigned int) rint( pow(2.0, m_spbtn_cm_depth->get_value()) ); } 00460 else 00461 { cm_depth = 1; } 00462 00463 unsigned int cm_width; 00464 if (m_spbtn_cm_width) 00465 { cm_width = (unsigned int) rint( pow(2.0, m_spbtn_cm_width->get_value()) ); } 00466 else 00467 { cm_width = 256; } 00468 00469 unsigned int cm_height; 00470 if (m_spbtn_cm_height) 00471 { cm_height = (unsigned int) rint( pow(2.0, m_spbtn_cm_height->get_value()) ); } 00472 else 00473 { cm_height = 256; } 00474 00475 if ( !m_generator 00476 || cm_depth != m_generator->get_current()->depth() 00477 || cm_width != m_generator->get_current()->width() 00478 || cm_height != m_generator->get_current()->height()) 00479 { 00480 delete m_generator; 00481 m_generator = new BayesColormapGenerator(cm_depth, H_UNKNOWN, cm_width, cm_height); 00482 m_cvw->set_colormap( m_generator->get_current() ); 00483 } 00484 00485 if (m_fg_object == H_UNKNOWN) 00486 { 00487 printf("CTW::add_to_colormap(): no fg object set\n"); 00488 return; 00489 } 00490 00491 m_generator->set_fg_object(m_fg_object); 00492 m_generator->reset_undo(); 00493 m_generator->set_buffer(m_src_buffer, m_img_width, m_img_height); 00494 m_generator->set_selection( m_zauberstab->getSelection() ); 00495 m_generator->consider(); 00496 m_generator->calc(); 00497 m_signal_colormap_updated(); 00498 00499 // update colormap image 00500 m_cvw->draw(-1); 00501 00502 // update segmentation image 00503 draw_segmentation_result(); 00504 } 00505 00506 /** Reset the colormap. */ 00507 void 00508 ColorTrainWidget::reset_colormap() 00509 { 00510 Gtk::MessageDialog dialog(*m_wnd_parent, "Are you sure you want to reset the colormap?", 00511 false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL); 00512 00513 int result = dialog.run(); 00514 00515 if (result != Gtk::RESPONSE_OK) return; 00516 00517 if (m_generator) 00518 { 00519 m_generator->reset(); 00520 m_signal_colormap_updated(); 00521 00522 if (m_cvw) 00523 { m_cvw->draw(); } 00524 00525 draw_segmentation_result(); 00526 } 00527 } 00528 00529 /** Open a dialog to load a colormap. */ 00530 void 00531 ColorTrainWidget::load_colormap() 00532 { 00533 if ( !m_fcd_filechooser ) 00534 { return; } 00535 00536 m_fcd_filechooser->set_title("Load colormap colormap"); 00537 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN); 00538 00539 m_fcd_filechooser->set_transient_for(*m_wnd_parent); 00540 00541 int result = m_fcd_filechooser->run(); 00542 00543 switch(result) 00544 { 00545 case (Gtk::RESPONSE_OK): 00546 { 00547 delete m_generator; 00548 00549 std::string filename = m_fcd_filechooser->get_filename(); 00550 ColormapFile cmf; 00551 cmf.read(filename.c_str()); 00552 Colormap *tcm = cmf.get_colormap(); 00553 YuvColormap *tycm = dynamic_cast<YuvColormap *>(tcm); 00554 if ( ! tycm ) { 00555 delete tcm; 00556 throw fawkes::TypeMismatchException("File does not contain a YUV colormap"); 00557 } 00558 unsigned int cm_depth = tcm->depth(); 00559 unsigned int cm_width = tcm->width(); 00560 unsigned int cm_height = tcm->height(); 00561 m_generator = new BayesColormapGenerator(cm_depth, H_UNKNOWN, cm_width, cm_height); 00562 YuvColormap *current = m_generator->get_current(); 00563 *current = *tycm; 00564 delete tcm; 00565 00566 if (m_spbtn_cm_depth) m_spbtn_cm_depth->set_value(log(cm_depth) / log(2)); 00567 if (m_spbtn_cm_width) m_spbtn_cm_width->set_value(log(cm_width) / log(2)); 00568 if (m_spbtn_cm_height) m_spbtn_cm_height->set_value(log(cm_height) / log(2)); 00569 00570 m_signal_colormap_updated(); 00571 m_cvw->set_colormap( m_generator->get_current() ); 00572 m_cvw->draw(); 00573 draw_segmentation_result(); 00574 break; 00575 } 00576 00577 case (Gtk::RESPONSE_CANCEL): 00578 break; 00579 00580 default: 00581 break; 00582 } 00583 00584 m_fcd_filechooser->hide(); 00585 } 00586 00587 /** Open a dialog to save a colormap. */ 00588 void 00589 ColorTrainWidget::save_colormap() 00590 { 00591 if ( !m_fcd_filechooser ) 00592 { return; } 00593 00594 m_fcd_filechooser->set_title("Save colormap colormap"); 00595 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_SAVE); 00596 00597 m_fcd_filechooser->set_transient_for(*m_wnd_parent); 00598 00599 int result = m_fcd_filechooser->run(); 00600 00601 switch(result) 00602 { 00603 case(Gtk::RESPONSE_OK): 00604 { 00605 std::string filename = m_fcd_filechooser->get_filename(); 00606 YuvColormap *current = m_generator->get_current(); 00607 ColormapFile cmf(current->depth(), current->width(), current->height()); 00608 cmf.add_colormap(current); 00609 cmf.write( filename.c_str() ); 00610 break; 00611 } 00612 00613 case(Gtk::RESPONSE_CANCEL): 00614 break; 00615 00616 default: 00617 break; 00618 } 00619 00620 m_fcd_filechooser->hide(); 00621 } 00622 00623 /** Get the current colormap. 00624 * @return the current colormap 00625 */ 00626 YuvColormap * 00627 ColorTrainWidget::get_colormap() const 00628 { 00629 if ( !m_generator ) 00630 { return 0; } 00631 00632 return m_generator->get_current(); 00633 } 00634 00635 bool 00636 ColorTrainWidget::set_threshold(Gtk::ScrollType scroll, double value) 00637 { 00638 unsigned int threshold = (unsigned int) rint(value); 00639 m_zauberstab->setThreshold(threshold); 00640 00641 return true; 00642 } 00643 00644 bool 00645 ColorTrainWidget::set_min_prob(Gtk::ScrollType scroll, double value) 00646 { 00647 if ( !m_generator ) 00648 { return true; } 00649 00650 m_generator->set_min_probability(value); 00651 00652 return true; 00653 } 00654 00655 void 00656 ColorTrainWidget::reset_gui() 00657 { 00658 m_scl_min_prob->set_value(0.0); 00659 } 00660 00661 /** Render the result of segmenting the image in the source buffer considering the current 00662 * colormap into the specified Image. 00663 */ 00664 void 00665 ColorTrainWidget::draw_segmentation_result() 00666 { 00667 if ( !m_src_buffer || !m_img_segmentation || !m_generator) 00668 { return; } 00669 00670 unsigned char* seg_buffer = (unsigned char*) malloc(m_img_size); 00671 bzero(seg_buffer, m_img_size); 00672 00673 Drawer d; 00674 d.set_buffer(seg_buffer, m_img_width, m_img_height); 00675 00676 YuvColormap* cm = m_generator->get_current(); 00677 00678 for (unsigned int w = 0; w < m_img_width; ++w) 00679 { 00680 for (unsigned int h = 0; h < m_img_height; ++h) 00681 { 00682 unsigned int y = YUV422_PLANAR_Y_AT(m_src_buffer, m_img_width, w, h); 00683 unsigned int u = YUV422_PLANAR_U_AT(m_src_buffer, m_img_width, m_img_height, w, h); 00684 unsigned int v = YUV422_PLANAR_V_AT(m_src_buffer, m_img_width, m_img_height, w, h); 00685 00686 d.set_color(ColorObjectMap::get_color(cm->determine(y, u, v))); 00687 d.color_point(w, h); 00688 } 00689 } 00690 00691 LossyScaler scaler; 00692 scaler.set_original_buffer(seg_buffer); 00693 scaler.set_original_dimensions(m_img_width, m_img_height); 00694 scaler.set_scaled_dimensions(m_seg_img_max_width, m_seg_img_max_height); 00695 unsigned int width = scaler.needed_scaled_width(); 00696 unsigned int height = scaler.needed_scaled_height(); 00697 00698 unsigned char* scaled_buffer = (unsigned char*) malloc( colorspace_buffer_size( m_img_cs, 00699 width, 00700 height ) ); 00701 scaler.set_scaled_buffer(scaled_buffer); 00702 scaler.scale(); 00703 00704 unsigned char* rgb_buffer = (unsigned char*) malloc( colorspace_buffer_size( RGB, 00705 width, 00706 height ) ); 00707 convert(m_img_cs, RGB, scaled_buffer, rgb_buffer, width, height); 00708 00709 Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_data( rgb_buffer, 00710 Gdk::COLORSPACE_RGB, 00711 false, 00712 8, 00713 width, 00714 height, 00715 3 * width, 00716 Gdk::Pixbuf::SlotDestroyData(&free_rgb_buffer)); 00717 00718 m_img_segmentation->set(image); 00719 00720 free(scaled_buffer); 00721 free(seg_buffer); 00722 } 00723 00724 /** Callback to free the rgb buffer 00725 * @param rgb_buffer pointer to the buffer 00726 */ 00727 void ColorTrainWidget::free_rgb_buffer(const guint8* rgb_buffer) 00728 { 00729 free(const_cast<guint8 *>(rgb_buffer)); 00730 }