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