image_display.cpp

00001
00002 /***************************************************************************
00003  *  image_display.cpp - widget to display an image based on SDL
00004  *
00005  *  Created: Mon Nov 05 14:19:26 2007
00006  *  Copyright  2007  Tim Niemueller [www.niemueller.de]
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. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program 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 Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include <fvwidgets/image_display.h>
00025
00026 #include <fvwidgets/sdl_keeper.h>
00027 #include <SDL.h>
00028
00029 #include <core/exception.h>
00030 #include <fvutils/color/conversions.h>
00031 #include <fvutils/color/yuv.h>
00032
00033 using namespace fawkes;
00034 
00035 /** @class ImageDisplay <fvwidgets/image_display.h>
00036  * Simple image display.
00037  * This is a simple thin wrapper around the SDL to display images in a standalone
00038  * window. Use this for instance for easy verification of vision results.
00039  * @author Tim Niemueller
00040  */
00041 
00042 /** Constructor.
00043  * @param width width of image
00044  * @param height height of image
00045  * @param title window title
00046  */
00047 ImageDisplay::ImageDisplay(unsigned int width, unsigned int height, const char* title)
00048 {
00049
00050   SDLKeeper::init(SDL_INIT_VIDEO);
00051   if (title) SDL_WM_SetCaption (title, NULL);
00052
00053   _width  = width;
00054   _height = height;
00055
00056   int bpp = SDL_VideoModeOK(_width, _height, 16, SDL_ANYFORMAT);
00057   _surface = SDL_SetVideoMode(width, height, bpp, /* flags */ SDL_HWSURFACE | SDL_ANYFORMAT);
00058   if ( ! _surface ) {
00059     throw Exception("SDL: cannot create surface");
00060   }
00061
00062   // SDL_UYVY_OVERLAY
00063   _overlay = SDL_CreateYUVOverlay(width, height, SDL_UYVY_OVERLAY, _surface);
00064   if ( ! _overlay ) {
00065     throw Exception("Cannot create overlay");
00066   }
00067
00068   _rect = new SDL_Rect;
00069
00070   _rect->x = 0;
00071   _rect->y = 0;
00072   _rect->w = _width;
00073   _rect->h = _height;
00074 }
00075
00076 
00077 /** Destructor. */
00078 ImageDisplay::~ImageDisplay()
00079 {
00080   delete _rect;
00081
00082   SDL_FreeYUVOverlay(_overlay);
00083   SDL_FreeSurface(_surface);
00084
00085   SDLKeeper::quit();
00086 }
00087
00088 
00089 /** Show image from given colorspace.
00090  * @param colorspace colorspace of the supplied buffer
00091  * @param buffer image buffer
00092  */
00093 void
00094 ImageDisplay::show(colorspace_t colorspace, unsigned char *buffer)
00095 {
00096   SDL_LockYUVOverlay(_overlay);
00097   convert(colorspace, YUV422_PACKED, buffer, _overlay->pixels[0], _width, _height);
00098   SDL_UnlockYUVOverlay(_overlay);
00099   SDL_DisplayYUVOverlay(_overlay, _rect);
00100 }
00101
00102 
00103 /** Show image from YUV422_PLANAR colorspace.
00104  * @param yuv422_planar_buffer YUV422_PLANAR encoded image.
00105  */
00106 void
00107 ImageDisplay::show(unsigned char *yuv422_planar_buffer)
00108 {
00109   SDL_LockYUVOverlay(_overlay);
00110
00111   yuv422planar_to_yuv422packed(yuv422_planar_buffer, _overlay->pixels[0],
00112                                _width, _height);
00113
00114   SDL_UnlockYUVOverlay(_overlay);
00115   SDL_DisplayYUVOverlay(_overlay, _rect);
00116 }
00117 
00118 /** Process a few SDL events.
00119  * @param max_num_events maximum number of events to process.
00120  */
00121 void
00122 ImageDisplay::process_events(unsigned int max_num_events)
00123 {
00124   unsigned int proc = 0;
00125   SDL_Event event;
00126   while ( (proc++ < max_num_events) && (SDL_PollEvent(&event)) ) {
00127     // nothing to do here
00128   }
00129 }
00130
00131 
00132 /** Process SDL events until quit.
00133  * Process SDL events and keeps the window responsive until either
00134  * the key "q" or "Esc" are pressed.
00135  */
00136 void
00137 ImageDisplay::loop_until_quit()
00138 {
00139   bool quit = false;
00140   while (! quit) {
00141     SDL_Event event;
00142     if ( SDL_WaitEvent(&event) ) {
00143       switch (event.type) {
00144       case SDL_QUIT:
00145         quit = true;
00146         break;
00147       case SDL_KEYUP:
00148         if ( (event.key.keysym.sym == SDLK_ESCAPE) ||
00149              (event.key.keysym.sym == SDLK_q) ) {
00150           quit = true;
00151         }
00152         break;
00153       }
00154     }
00155   }
00156 }