Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phFLImageWindow.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #include <phFLImageWindow.h>
00033 
00034 #include <phError.h>
00035 #include <phMemory.h>
00036 #include <phPrint.h>
00037 
00038 /* ---------------------------------------------------------------------- */
00039 static void on_close_window(Fl_Widget *widget, void *ptr)
00040 {
00041     phFUNCTION("on_close_window")
00042 
00043     phFLImageWindow *fl_window = (phFLImageWindow *)widget;
00044         
00045     fl_window->user_close(ptr);
00046 }
00047 
00048 /* ---------------------------------------------------------------------- */
00049 phFLImageWindow::phFLImageWindow( int32_t x, int32_t y,
00050                                   uint32_t w, uint32_t h,
00051                                   char *title,
00052                                   uint32_t flags ) :
00053                 Fl_Double_Window(0,0,w,h,title),
00054                 phImageWindow(x,y,w,h,title,flags )
00055 {
00056     phFUNCTION("phFLImageWindow::phFLImageWindow")
00057     
00058     /*
00059     uint32_t max_width   = 0;
00060     uint32_t max_height  = 0;
00061     */
00062     rc = this->lock();
00063     phPRINT_RC(rc,NULL,"this->lock() failed.");
00064     
00065     this->m_redraw = 0;
00066     this->m_exit_now = 0;
00067 
00068     this->size_range( this->m_min_width, this->m_min_height,
00069                        36000, 24000 );
00070    
00071     this->Fl_Double_Window::callback(on_close_window,
00072                                      (void *)&this->m_exit_now);
00073     rc = Fl::visual(FL_DOUBLE|FL_INDEX|FL_RGB);
00074    
00075     this->m_formats = phImageRGB24 | phImageRGBA32 | phImageGREY8;
00076     
00077     rc = this->unlock();
00078     phPRINT_RC(rc,NULL,"this->unlock() failed.");
00079 }
00080 
00081 /* ---------------------------------------------------------------------- */
00082 phFLImageWindow::~phFLImageWindow()
00083 {
00084     phFUNCTION("phFLImageWindow::~phFLImageWindow")
00085 
00086     int locked = 0;
00087 
00088     phTHIS_LOCK(locked);
00089 error:
00090     return;
00091 }
00092 
00093 /* ---------------------------------------------------------------------- */
00094 int phFLImageWindow::private_show( )
00095 {
00096     /* phFUNCTION("phFLImageWindow::private_show") */
00097     /* 
00098      * We are locked when we get into a "private" method; Locking is done 
00099      * as a policy in any public interface method that calls a private 
00100      * (implementation specific) method 
00101     int locked = 1;
00102      */
00103     
00104     this->Fl_Double_Window::show();
00105     
00106     return phSUCCESS;
00107 }    
00108 
00109 /* ---------------------------------------------------------------------- */
00110 int phFLImageWindow::private_hide( )
00111 {
00112     /*phFUNCTION("phFLImageWindow::private_hide")*/
00113     /* 
00114      * We are locked when we get into a "private" method; Locking is done 
00115      * as a policy in any public interface method that calls a private 
00116      * (implementation specific) method 
00117     int locked = 1;
00118      */
00119     
00120     this->Fl_Double_Window::hide();
00121     
00122     return phSUCCESS;
00123 }
00124 
00125 /* ---------------------------------------------------------------------- */
00126 int phFLImageWindow::private_update()
00127 {
00128     phFUNCTION("phFLImageWindow::update")
00129     /* 
00130      * We are locked when we get into a "private" method; Locking is done 
00131      * as a policy in any public interface method that calls a private 
00132      * (implementation specific) method 
00133     int locked = 1;
00134      */
00135     int writeLocked = 0;
00136    
00137     rc = this->m_image.writeLock();
00138     phCHECK_RC(rc,NULL,"this->m_image.writeLock() failed.");
00139     writeLocked = 1;
00140 
00141     if (!this->m_image.isNull())
00142     {
00143         /* if we need to redraw, then redraw */
00144         this->private_redraw();
00145     }
00146     
00147     rc = this->m_image.rwUnlock();
00148     writeLocked = 0;
00149     phCHECK_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00150 
00151     return phSUCCESS;
00152     
00153 error:
00154     if (writeLocked)
00155     {
00156         rc = this->m_image.rwUnlock();
00157         phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00158         writeLocked = 0;
00159     }
00160 
00161     return phFAIL;
00162 }
00163 
00164 /* ---------------------------------------------------------------------- */
00165 void phFLImageWindow::draw()
00166 {
00167     phFUNCTION("phFLImageWindow::draw")
00168     uint8_t *img = NULL;
00169     #if defined(WIN32)
00170     int x = 0;
00171     int y = 0;
00172     #endif
00173     int locked      = 0;
00174     int writeLocked = 0;
00175     /* 
00176      * This is for RGB
00177      * void fl_draw_image(const uchar *, int X, int Y, 
00178      *                    int W, int H, int D = 3, int LD = 0)
00179      *                    
00180      * This is for Greyscale
00181      * void fl_draw_image_mono(const uchar *, int X, int Y, 
00182      *                         int W, int H, int D = 1, int LD = 0)
00183      */
00184 
00185     phTHIS_LOCK(locked);
00186 
00187     if (this->m_redraw == 0) 
00188     {
00189         DEBUG_PRINT("FLTK called draw\n");
00190         goto error;
00191     }
00192    
00193 #if 0
00194     /* This is here because phDisplayInterface locks the local m_image
00195      * and could potentially deadlock. We only want to redraw if we're
00196      * explicitly told to by phDisplayInterface so the check above
00197      * for m_redraw should prevent a dead lock. This is commented out
00198      * as a reminder of the situation. */
00199     rc = this->m_image.tryWriteLock();
00200     if (rc == 1)
00201     {
00202         DEBUG_PRINT("Failed redraw\n");
00203         goto error;
00204     }
00205     phCHECK_RC(rc,NULL,"this->m_image.tryWriteLock() failed.");
00206 #else
00207     rc = this->m_image.writeLock();
00208     phCHECK_RC(rc,NULL,"this->m_image.writeLock() failed.");
00209 
00210 #endif
00211     writeLocked = 1;
00212    
00213     if (!this->m_image.isNull())
00214     {
00215         rc = this->m_image.convert( this->getFormats(),phImageRGB24);
00216         phPRINT_RC(rc,NULL,"m_image.convert();");
00217         
00218         if (this->m_image.getFormat() & this->getFormats())
00219         {
00220             int depth = 0;
00221             
00222             this->m_image.resize(this->phImageWindow::m_w,this->phImageWindow::m_h);
00223           
00224             /* Try to remove any special flags */
00225             /* The format will be one of the following after
00226              * the convert call above */
00227             switch (this->m_image.getFormat())
00228             {
00229                 case phImageRGB24:
00230                     depth = 24;
00231                     break;
00232                 case phImageRGBA32:
00233                     depth = 32;
00234                     break;
00235                 case phImageGREY8:
00236                     depth = 8;
00237                     break;
00238                 default:
00239                     rc = this->m_image.convert(phImageRGB24);
00240                     if (rc != 0)
00241                         /* depth = 0 will prevent the image from being drawn */
00242                         depth = 0;
00243                     else
00244                         depth = 24;
00245                     break;
00246             };
00247             
00248             img = (uint8_t *)this->m_image.getData();
00249             
00250             if (img == NULL) goto error;
00251             
00252             #if defined(WIN32)
00253             x=this->x();
00254             y=this->y();
00255             #endif
00256             
00257             if (depth > 16)
00258             {
00259                 fl_draw_image(img,
00260                         0,0, 
00261                         this->m_image.getWidth(),
00262                         this->m_image.getHeight(),
00263                         depth / 8);
00264             }
00265             else if (depth > 0)
00266             {
00267                 fl_draw_image_mono(img,
00268                         0,0, 
00269                         this->m_image.getWidth(),
00270                         this->m_image.getHeight(),
00271                         depth / 8);
00272             }
00273 
00274             /* maintain frames-per-second */
00275             this->tickFrame();
00276         }
00277         /* else if (this->m_image.getFormat() & ImageYUV) { } */
00278     }
00279 error:
00280     if (this->m_redraw > 0) this->m_redraw = 0;
00281     
00282     if (writeLocked)
00283     {
00284         rc = this->m_image.rwUnlock();
00285         phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00286         writeLocked = 0;
00287     }
00288 
00289     phTHIS_ERROR_UNLOCK(locked);
00290     
00291     return;
00292 }
00293 
00294 /* ---------------------------------------------------------------------- */
00295 int phFLImageWindow::private_redraw()
00296 {
00297     phFUNCTION("phFLImageWindow::private_redraw")
00298     /* 
00299      * We are locked when we get into a "private" method; Locking is done 
00300      * as a policy in any public interface method that calls a private 
00301      * (implementation specific) method 
00302     int locked = 1;
00303      */
00304     
00305     this->m_redraw = 1; 
00306     this->draw();
00307 
00308     return phSUCCESS;
00309 }
00310 
00311 /* ---------------------------------------------------------------------- */
00312 void phFLImageWindow::resize( int x, int y, int w, int h )
00313 {
00314     phFUNCTION("phFLImageWindow::resize")
00315     int locked = 0;
00316     uint32_t lw = w;
00317     uint32_t lh = h;
00318    
00319     if ((w <= 0) || h <= 0) return;
00320     
00321     phTHIS_LOCK(locked);
00322 
00323     if ((lh != this->phImageWindow::m_h) || 
00324         (lw != this->phImageWindow::m_w) ||
00325         (x != this->phImageWindow::m_x) || 
00326         (y != this->phImageWindow::m_y))
00327     {
00328         this->phImageWindow::m_x = x;
00329         this->phImageWindow::m_y = y;
00330         this->phImageWindow::m_w = lw;
00331         this->phImageWindow::m_h = lh;
00332         
00333         Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y,
00334                                  this->phImageWindow::m_w,this->phImageWindow::m_h);
00335     }
00336 
00337     phTHIS_UNLOCK(locked);
00338 
00339     return;
00340 error:
00341     phTHIS_ERROR_UNLOCK(locked);
00342     
00343     return;
00344 }
00345 
00346 /* ---------------------------------------------------------------------- */
00347 int phFLImageWindow::private_resize( uint32_t w, uint32_t h)
00348 {
00349     phFUNCTION("phFLImageWindow::private_resize")
00350     /* 
00351      * We are locked when we get into a "private" method; Locking is done 
00352      * as a policy in any public interface method that calls a private 
00353      * (implementation specific) method 
00354     int locked = 1;
00355      */
00356     
00357     if ((h != this->phImageWindow::m_h) || (w != this->phImageWindow::m_w))
00358     {
00359         this->phImageWindow::m_w = w;
00360         this->phImageWindow::m_h = h;
00361         
00362         Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y,
00363                                  this->phImageWindow::m_w,this->phImageWindow::m_h);
00364     }
00365 
00366     return phSUCCESS;
00367 }    
00368 
00369 /* ---------------------------------------------------------------------- */
00370 int phFLImageWindow::private_move( int32_t x, int32_t y)
00371 {
00372     phFUNCTION("phFLImageWindow::private_move")
00373     /* 
00374      * We are locked when we get into a "private" method; Locking is done 
00375      * as a policy in any public interface method that calls a private 
00376      * (implementation specific) method 
00377     int locked = 1;
00378      */
00379     
00380     if ((x != this->phImageWindow::m_x) || (y != this->phImageWindow::m_y))
00381     {
00382         this->phImageWindow::m_x = x;
00383         this->phImageWindow::m_y = y;
00384         
00385         Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y,
00386                                  this->phImageWindow::m_w,this->phImageWindow::m_h);
00387     }
00388 
00389     return phSUCCESS;
00390 }    
00391 
00392 /* ---------------------------------------------------------------------- */
00393 int phFLImageWindow::private_minsize( uint32_t min_w, uint32_t min_h)
00394 {
00395     phFUNCTION("phFLImageWindow::private_minsize")
00396     /* 
00397      * We are locked when we get into a "private" method; Locking is done 
00398      * as a policy in any public interface method that calls a private 
00399      * (implementation specific) method 
00400     int locked = 1;
00401      */
00402     
00403     this->size_range( min_w, min_h, 36000, 24000 );
00404 
00405     return phSUCCESS;
00406 }    
00407 
00408 /* ---------------------------------------------------------------------- */
00409 void phFLImageWindow::user_close(void *ptr)
00410 {
00411     phFUNCTION("phFLImageWindow::user_close")
00412     volatile int *exit_now = (volatile int *)ptr;
00413     int locked = 0;
00414     
00415     phTHIS_LOCK(locked);
00416 
00417     if (this->isOpen())
00418     {
00419         this->hide();
00420         
00421         if (exit_now != NULL)
00422         {
00423             *exit_now = 1;
00424         }
00425         
00426         rc = this->m_image.wakeup_self();
00427         phPRINT_RC(rc,NULL,"this->m_image.wakeup_self() failed.");
00428 
00429         phTHIS_UNLOCK(locked);
00430         
00431         Fl::atclose(this, ptr);
00432     }
00433     else
00434     {
00435         phTHIS_UNLOCK(locked);
00436     }
00437     return;
00438 error:
00439     phTHIS_ERROR_UNLOCK(locked);
00440     return;
00441 }
00442 
00443 /* ---------------------------------------------------------------------- */
00444 int phFLImageWindow::isOpen()
00445 {
00446     return this->isRunning();
00447 }
00448 
00449 /* ---------------------------------------------------------------------- */
00450 int phFLImageWindow::handle(int event) 
00451 {
00452     switch(event) {
00453         case FL_KEYDOWN:
00454             if (Fl::event_key() == 'q') 
00455             {
00456                 this->user_close((void *)&this->m_exit_now);
00457                 return 1;
00458             }
00459             else
00460             {
00461                 return Fl_Widget::handle(event);
00462             }
00463             
00464             break;
00465         default:
00466             return Fl_Widget::handle(event);
00467     }
00468 
00469     return 0;
00470 }
00471 
00472 /* ---------------------------------------------------------------------- */
00473 int phFLImageWindow::setup()
00474 {
00475     phFUNCTION("phFLImageWindow::setup")
00476   
00477     this->m_exit_now = 0;
00478    
00479     return phSUCCESS;
00480 }
00481 
00482 /* ---------------------------------------------------------------------- */
00483 int phFLImageWindow::wakeup()
00484 {
00485     phFUNCTION("phFLImageWindow::wakeup")
00486 
00487     this->m_image.wakeup_self();
00488    
00489     return phSUCCESS;
00490 }
00491 
00492 /* ---------------------------------------------------------------------- */
00493 int phFLImageWindow::run()
00494 {
00495     phFUNCTION("phFLImageWindow::run")
00496     
00497     DEBUG_PRINT("Thread started\n");
00498    
00499     this->phImageWindow::show();
00500     
00501     rc = this->signal_running();
00502     phCHECK_RC(rc,NULL,"this->signal_running()");
00503     
00504     while ((this->isRunning()) && (this->m_exit_now == 0))
00505     {
00506         /* Handle GUI EVENTS */
00507 #define LOCKEM() 1 
00508         /* Must lock, otherwise, the Fl::check() could collide with another
00509          * function call and cause the "unexpected async reply" on X systems 
00510          */
00511 #if 1
00512     #if LOCKEM()
00513         rc = this->lock();
00514         phPRINT_RC(rc,NULL,"fl_window->lock() failed.");
00515     #endif
00516 
00517         rc = Fl::check();
00518         
00519     #if LOCKEM()
00520         rc = this->unlock();
00521         phPRINT_RC(rc,NULL,"fl_window->unlock() failed.");
00522     #endif
00523 
00524     #if 0
00525         phYield();
00526     #else
00527         phMSleep(0);
00528     #endif
00529 #else
00530         /* Still no way to wake up a blocked window from this */
00531         rc = Fl::wait();
00532 #endif
00533     }
00534 
00535     this->hide();
00536 
00537     DEBUG_PRINT("Thread returning with success\n");
00538     
00539     return phSUCCESS;
00540 error:
00541     phPROGRESS("Thread returning with error\n");
00542 
00543     rc = this->signal_error();
00544     phPRINT_RC(rc,NULL,"this->signal_error()");
00545 
00546     this->hide();
00547 
00548     return phFAIL;
00549     
00550 }
00551 
00552 void phFLImageWindow::hide() 
00553 { 
00554     this->phImageWindow::hide(); 
00555 }
00556 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4