00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "image_widget.h"
00024
00025 #include <core/exceptions/software.h>
00026 #include <core/threading/mutex.h>
00027 #include <fvutils/color/conversions.h>
00028 #include <fvutils/color/yuv.h>
00029 #include <fvutils/scalers/lossy.h>
00030 #include <cams/camera.h>
00031
00032 #include <iomanip>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 ImageWidget::ImageWidget(unsigned int width, unsigned int height)
00048 {
00049 __cam = NULL;
00050 __cam_enabled = false;
00051 __cam_mutex = new fawkes::Mutex;
00052 __refresh_thread = NULL;
00053
00054 set_size(width, height);
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 ImageWidget::ImageWidget(Camera *cam, unsigned int refresh_delay, unsigned int width, unsigned int height)
00068 {
00069 if (!cam) throw fawkes::NullPointerException("Parameter cam may not be NULL");
00070
00071 __cam = cam;
00072 __cam_enabled = true;
00073 __cam_mutex = new fawkes::Mutex;
00074 __cam_has_buffer = false;
00075
00076 set_size(width, height);
00077
00078 try {
00079 fawkes::Time *time = __cam->capture_time();
00080 delete time;
00081 __cam_has_timestamp = true;
00082 }
00083 catch (fawkes::Exception &e) {
00084 __cam_has_timestamp = false;
00085 }
00086
00087 __refresh_thread = new RefThread(this, refresh_delay);
00088 __refresh_thread->start();
00089 __refresh_thread->refresh_cam();
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 ImageWidget::ImageWidget(BaseObjectType* cobject, Glib::RefPtr<Gnome::Glade::Xml> refxml)
00104 : Gtk::Image( cobject )
00105 {
00106 __cam = NULL;
00107 __cam_enabled = false;
00108 __cam_mutex = new fawkes::Mutex;
00109 __refresh_thread = NULL;
00110
00111
00112 }
00113
00114
00115
00116
00117 ImageWidget::~ImageWidget()
00118 {
00119 if (__refresh_thread) __refresh_thread->stop();
00120 delete __cam_mutex;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 void
00133 ImageWidget::set_camera(Camera *cam, unsigned int refresh_delay)
00134 {
00135 __cam = cam;
00136 __cam_enabled = true;
00137 __cam_has_buffer = false;
00138
00139 set_size(__cam->pixel_width(), __cam->pixel_height());
00140
00141 try {
00142 fawkes::Time *time = __cam->capture_time();
00143 delete time;
00144 __cam_has_timestamp = true;
00145 }
00146 catch (fawkes::Exception &e) {
00147 __cam_has_timestamp = false;
00148 }
00149
00150 if ( __refresh_thread ) {
00151 __refresh_thread->set_delay(refresh_delay);
00152 } else {
00153 __refresh_thread = new RefThread(this, refresh_delay);
00154 __refresh_thread->start();
00155 }
00156
00157 __refresh_thread->refresh_cam();
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 void
00167 ImageWidget::enable_camera(bool enable)
00168 {
00169 if ( !enable && __cam_enabled ) {
00170 __refresh_thread->stop();
00171 } else if ( __refresh_thread && enable && !__cam_enabled ) {
00172 __refresh_thread->start();
00173 }
00174
00175 __cam_enabled = enable;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void
00189 ImageWidget::set_size(unsigned int width, unsigned int height)
00190 {
00191 if (!width || ! height) {
00192 if (__cam) {
00193 width = __cam->pixel_width();
00194 height = __cam->pixel_height();
00195 }
00196 else {
00197 throw fawkes::IllegalArgumentException("ImageWidget::set_size(): width and/or height may not be 0 if no Camera is set");
00198 }
00199 }
00200
00201 if (!__pixbuf || __width != width || __height != height) {
00202 __width = width;
00203 __height = height;
00204
00205 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 16 )
00206 __pixbuf.reset();
00207 #else
00208 __pixbuf.clear();
00209 #endif
00210
00211 __pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, __width, __height);
00212
00213 set_size_request(__width, __height);
00214 }
00215 }
00216
00217
00218
00219
00220 unsigned int
00221 ImageWidget::get_width() const
00222 {
00223 return __width;
00224 }
00225
00226
00227
00228
00229
00230 unsigned int
00231 ImageWidget::get_height() const
00232 {
00233 return __height;
00234 }
00235
00236
00237
00238
00239
00240 Glib::RefPtr<Gdk::Pixbuf>
00241 ImageWidget::get_buffer() const
00242 {
00243 return __pixbuf;
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 void
00256 ImageWidget::set_rgb(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b)
00257 {
00258 set_rgb (x, y, (RGB_t){r, g, b});
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268 void
00269 ImageWidget::set_rgb(unsigned int x, unsigned int y, RGB_t rgb)
00270 {
00271 if (x >= __width) throw fawkes::OutOfBoundsException("x-Coordinate exeeds image width", x, 0, __width);
00272 if (y >= __height) throw fawkes::OutOfBoundsException("y-Coordinate exeeds image height", x, 0, __height);
00273
00274 RGB_t * target = RGB_PIXEL_AT(__pixbuf->get_pixels(), __width, x, y);
00275 *target = rgb;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 bool
00292 ImageWidget::show(colorspace_t colorspace, unsigned char *buffer, unsigned int width, unsigned int height)
00293 {
00294 try {
00295 if (!width || !height || (width == __width && height == __height)) {
00296 convert(colorspace, RGB, buffer, __pixbuf->get_pixels(), __width, __height);
00297 }
00298 else {
00299 unsigned char *scaled_buffer = (unsigned char *)malloc(colorspace_buffer_size(colorspace, __width, __height));
00300
00301 if (scaled_buffer) {
00302 LossyScaler scaler;
00303 scaler.set_original_buffer(buffer);
00304 scaler.set_original_dimensions(width, height);
00305 scaler.set_scaled_buffer(scaled_buffer);
00306 scaler.set_scaled_dimensions(__width, __height);
00307 scaler.scale();
00308
00309 convert(colorspace, RGB, scaled_buffer, __pixbuf->get_pixels(), __width, __height);
00310
00311 free(scaled_buffer);
00312 }
00313 }
00314 }
00315 catch (fawkes::Exception &e) {
00316 printf("ImageWidget::show(): %s\n", e.what());
00317 return false;
00318 }
00319
00320 try {
00321 set(__pixbuf);
00322 __signal_show.emit(colorspace, buffer, width, height);
00323 return true;
00324 }
00325 catch (fawkes::Exception &e) {
00326 printf("ImageWidget::show(): Could not set the new image (%s)\n", e.what());
00327 }
00328
00329 return false;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 sigc::signal<void, colorspace_t, unsigned char *, unsigned int, unsigned int> &
00343 ImageWidget::signal_show()
00344 {
00345 return __signal_show;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 void
00355 ImageWidget::set_refresh_delay(unsigned int refresh_delay)
00356 {
00357 __refresh_thread->set_delay(refresh_delay);
00358 }
00359
00360
00361
00362
00363
00364 void
00365 ImageWidget::refresh_cam()
00366 {
00367 if ( __cam_enabled ) {
00368 __refresh_thread->refresh_cam();
00369 }
00370 }
00371
00372
00373
00374
00375
00376 void
00377 ImageWidget::set_cam()
00378 {
00379 if ( !__cam_enabled ) { return; }
00380
00381 __cam_mutex->lock();
00382
00383 if (__cam_has_buffer) {
00384 show(__cam->colorspace(), __cam->buffer(), __cam->pixel_width(), __cam->pixel_height());
00385 __cam->flush();
00386 __cam_has_buffer = false;
00387 }
00388
00389 __cam_mutex->unlock();
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 bool
00402 ImageWidget::save_image(std::string filename, Glib::ustring type) const throw()
00403 {
00404 __cam_mutex->lock();
00405
00406 try {
00407 __pixbuf->save(filename, type);
00408 __cam_mutex->unlock();
00409 return true;
00410 }
00411 catch (Glib::Exception &e) {
00412 __cam_mutex->unlock();
00413 printf("save failed: %s\n", e.what().c_str());
00414 return false;
00415 }
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 void
00428 ImageWidget::save_on_refresh_cam(bool enable, std::string path, Glib::ustring type, unsigned int img_num)
00429 {
00430 __refresh_thread->save_on_refresh(enable, path, type, img_num);
00431 }
00432
00433
00434
00435
00436
00437 unsigned int
00438 ImageWidget::get_image_num()
00439 {
00440 return __refresh_thread->get_img_num();
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 ImageWidget::RefThread::RefThread(ImageWidget *widget, unsigned int refresh_delay)
00450 : Thread("ImageWidget refresh thread")
00451 {
00452 set_delete_on_exit(true);
00453
00454 __widget = widget;
00455 __stop = false;
00456 __do_refresh = false;
00457
00458 __save_imgs = false;
00459 __save_num = 0;
00460
00461 __dispatcher.connect( sigc::mem_fun( *widget , &ImageWidget::set_cam ) );
00462
00463 set_delay(refresh_delay);
00464 }
00465
00466
00467
00468
00469
00470
00471 void
00472 ImageWidget::RefThread::set_delay(unsigned int refresh_delay)
00473 {
00474 __refresh_delay = refresh_delay;
00475 __loop_cnt = 0;
00476 }
00477
00478
00479
00480
00481 void
00482 ImageWidget::RefThread::refresh_cam()
00483 {
00484 __do_refresh = true;
00485 }
00486
00487
00488
00489
00490 void
00491 ImageWidget::RefThread::perform_refresh()
00492 {
00493 if (!__widget->__cam) {
00494 throw fawkes::NullPointerException("Camera hasn't been given during creation");
00495 }
00496
00497 try {
00498 if (__widget->__cam_mutex->try_lock()) {
00499 __widget->__cam->dispose_buffer();
00500 __widget->__cam->capture();
00501 if (!__stop) {
00502 __widget->__cam_has_buffer = true;
00503 __widget->__cam_mutex->unlock();
00504
00505 if (__widget->__cam->ready()) {
00506 __dispatcher();
00507
00508 if (__save_imgs) {
00509 char *ctmp;
00510 if (__widget->__cam_has_timestamp) {
00511 try {
00512 fawkes::Time *ts = __widget->__cam->capture_time();
00513 if (asprintf(&ctmp, "%s/%06u.%ld.%s", __save_path.c_str(), ++__save_num, ts->in_msec(), __save_type.c_str()) != -1) {
00514 Glib::ustring fn = ctmp;
00515 __widget->save_image(fn, __save_type);
00516 free(ctmp);
00517 } else {
00518 printf("Cannot save image, asprintf() ran out of memory\n");
00519 }
00520 delete ts;
00521 }
00522 catch (fawkes::Exception &e) {
00523 printf("Cannot save image (%s)\n", e.what());
00524 }
00525 }
00526 else {
00527 if (asprintf(&ctmp, "%s/%06u.%s", __save_path.c_str(), ++__save_num, __save_type.c_str()) != -1) {
00528 Glib::ustring fn = ctmp;
00529 __widget->save_image(fn, __save_type);
00530 free(ctmp);
00531 } else {
00532 printf("Cannot save image, asprintf() ran out of memory\n");
00533 }
00534 }
00535 }
00536 }
00537 }
00538 }
00539 }
00540 catch (fawkes::Exception &e) {
00541 printf("Could not capture the image (%s)\n", e.what());
00542 }
00543 }
00544
00545
00546 void
00547 ImageWidget::RefThread::loop()
00548 {
00549 if (!__stop) {
00550 ++__loop_cnt;
00551
00552 if (__refresh_delay && !(__loop_cnt % __refresh_delay)) {
00553 perform_refresh();
00554 __do_refresh = false;
00555 __loop_cnt = 0;
00556 }
00557
00558 if (__do_refresh) {
00559 perform_refresh();
00560 __do_refresh = false;
00561 __loop_cnt = 0;
00562 }
00563 }
00564 else exit();
00565
00566 Glib::usleep(1000);
00567 }
00568
00569
00570
00571
00572 void
00573 ImageWidget::RefThread::stop()
00574 {
00575 __stop = true;
00576 }
00577
00578
00579 void
00580 ImageWidget::RefThread::save_on_refresh(bool enabled, std::string path, Glib::ustring type, unsigned int img_num)
00581 {
00582 __save_imgs = enabled;
00583
00584 if (__save_imgs) {
00585 __save_path = path;
00586 __save_type = type;
00587 __save_num = img_num;
00588 }
00589 }
00590
00591 unsigned int
00592 ImageWidget::RefThread::get_img_num()
00593 {
00594 return __save_num;
00595 }