fuse_image_content.cpp

00001 
00002 /***************************************************************************
00003  *  fuse_image_content.cpp - FUSE image content encapsulation
00004  *
00005  *  Created: Thu Nov 15 15:55:51 2007
00006  *  Copyright  2005-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 <fvutils/net/fuse_image_content.h>
00025 #include <fvutils/ipc/shm_image.h>
00026 #include <fvutils/color/conversions.h>
00027 #include <fvutils/compression/jpeg_decompressor.h>
00028 
00029 #include <core/exceptions/system.h>
00030 #include <core/exceptions/software.h>
00031 
00032 #include <cstdlib>
00033 #include <netinet/in.h>
00034 #include <cstring>
00035 
00036 namespace firevision {
00037 #if 0 /* just to make Emacs auto-indent happy */
00038 }
00039 #endif
00040 
00041 /** @class FuseImageContent <fvutils/net/fuse_image_content.h>
00042  * FUSE image content.
00043  * @ingroup FUSE
00044  * @ingroup FireVision
00045  * @author Tim Niemueller
00046  */
00047 
00048 /** Constructor.
00049  * @param type message type
00050  * @param payload payload
00051  * @param payload_size size of payload
00052  */
00053 FuseImageContent::FuseImageContent(uint32_t type,
00054                                    void *payload, size_t payload_size)
00055 {
00056   if ( type != FUSE_MT_IMAGE ) {
00057     throw fawkes::TypeMismatchException("Type %u != FUSE_MT_IMAGE (%u)", type, FUSE_MT_IMAGE);
00058   }
00059 
00060   _payload_size = payload_size;
00061   _payload      = payload;
00062 
00063   __header = (FUSE_image_message_header_t *)_payload;
00064   __buffer = (unsigned char *)_payload + sizeof(FUSE_image_message_header_t);
00065   __capture_time = new fawkes::Time(ntohl(__header->capture_time_sec),
00066                                     ntohl(__header->capture_time_usec));
00067 
00068   __buffer_size = ntohl(__header->buffer_size);
00069 }
00070 
00071 
00072 /** Constructor.
00073  * Copies data from given buffer.
00074  * @param b shared memory image buffer to copy image from
00075  */
00076 FuseImageContent::FuseImageContent(SharedMemoryImageBuffer *b)
00077 {
00078   __buffer_size  = colorspace_buffer_size(b->colorspace(), b->width(), b->height());
00079   _payload_size  = __buffer_size + sizeof(FUSE_image_message_header_t);
00080   _payload = malloc(_payload_size);
00081 
00082   if ( _payload == NULL ) {
00083     throw fawkes::OutOfMemoryException("Cannot allocate FuseImageContent buffer");
00084   }
00085 
00086   __header = (FUSE_image_message_header_t *)_payload;
00087   __buffer = (unsigned char *)_payload + sizeof(FUSE_image_message_header_t);
00088 
00089   strncpy(__header->image_id, b->image_id(), IMAGE_ID_MAX_LENGTH);
00090   __header->format = FUSE_IF_RAW;
00091   __header->colorspace = htons(b->colorspace());
00092   __header->reserved = 0;
00093   __header->width  = htonl(b->width());
00094   __header->height = htonl(b->height());
00095   __header->buffer_size = htonl(__buffer_size);
00096 
00097   long int cts = 0, ctus = 0;
00098   b->capture_time(&cts, &ctus);
00099   __header->capture_time_sec = htonl(cts);
00100   __header->capture_time_usec = htonl(ctus);
00101 
00102   __capture_time = NULL;
00103 
00104   b->lock_for_read();
00105   memcpy(__buffer, b->buffer(), __buffer_size);
00106   b->unlock();
00107 }
00108 
00109 
00110 /** Constructor.
00111  * Copies data from given buffer.
00112  * @param image_format image format
00113  * @param image_id image ID
00114  * @param buffer image buffer, encoded according to image_format
00115  * @param buffer_size size of buffer in bytes
00116  * @param colorspace color space
00117  * @param width width of image in pixels
00118  * @param height height of image in pixels
00119  * @param capture_time_sec optional seconds part of the capture time
00120  * @param capture_time_usec optional microseconds part of the capture time
00121  */
00122 FuseImageContent::FuseImageContent(FUSE_image_format_t image_format, const char *image_id,
00123                                    unsigned char *buffer, size_t buffer_size,
00124                                    colorspace_t colorspace,
00125                                    unsigned int width, unsigned int height,
00126                                    long int capture_time_sec,
00127                                    long int capture_time_usec)
00128 {
00129   __buffer_size  = buffer_size;
00130   _payload_size  = __buffer_size + sizeof(FUSE_image_message_header_t);
00131   _payload = malloc(_payload_size);
00132 
00133   if ( _payload == NULL ) {
00134     throw fawkes::OutOfMemoryException("Cannot allocate FuseImageContent buffer");
00135   }
00136 
00137   __header = (FUSE_image_message_header_t *)_payload;
00138   __buffer = (unsigned char *)_payload + sizeof(FUSE_image_message_header_t);
00139 
00140   strncpy(__header->image_id, image_id, IMAGE_ID_MAX_LENGTH);
00141   __header->format = image_format;
00142   __header->colorspace = htons(colorspace);
00143   __header->reserved = 0;
00144   __header->width  = htonl(width);
00145   __header->height = htonl(height);
00146   __header->buffer_size = htonl(__buffer_size);
00147   __header->capture_time_sec = htonl(capture_time_sec);
00148   __header->capture_time_usec = htonl(capture_time_usec);
00149 
00150   __capture_time = NULL;
00151 
00152   memcpy(__buffer, buffer, __buffer_size);
00153 }
00154 
00155 
00156 /** Destructor. */
00157 FuseImageContent::~FuseImageContent()
00158 {
00159   delete __capture_time;
00160 }
00161 
00162 /** Image buffer.
00163  * @return image buffer
00164  */
00165 unsigned char *
00166 FuseImageContent::buffer() const
00167 {
00168   return __buffer;
00169 }
00170 
00171 
00172 /** Get size of buffer.
00173  * @return size of buffer returned by buffer()
00174  */
00175 size_t
00176 FuseImageContent::buffer_size() const
00177 {
00178   return __buffer_size;
00179 }
00180 
00181 
00182 /** Get image width.
00183  * @return width of image in pixels
00184  */
00185 unsigned int
00186 FuseImageContent::pixel_width() const
00187 {
00188   return ntohl(__header->width);
00189 }
00190 
00191 
00192 /** Get image height.
00193  * @return height of image in pixels
00194  */
00195 unsigned int
00196 FuseImageContent::pixel_height() const
00197 {
00198   return ntohl(__header->height);
00199 }
00200 
00201 
00202 /** Get colorspace.
00203  * @return colorspace
00204  */
00205 unsigned int
00206 FuseImageContent::colorspace() const
00207 {
00208   return ntohs(__header->colorspace);
00209 }
00210 
00211 
00212 /** Get image format.
00213  * @return format
00214  */
00215 unsigned int
00216 FuseImageContent::format() const
00217 {
00218   return __header->format;
00219 }
00220 
00221 
00222 /** Get capture time.
00223  * @return capture time
00224  */
00225 fawkes::Time *
00226 FuseImageContent::capture_time() const
00227 {
00228   if ( ! __capture_time ) {
00229     __capture_time = new fawkes::Time(ntohl(__header->capture_time_sec),
00230                                       ntohl(__header->capture_time_usec));
00231   }
00232   return __capture_time;
00233 }
00234 
00235 void
00236 FuseImageContent::serialize()
00237 {
00238   // Nothing to do here
00239 }
00240 
00241 
00242 /** Decompress image data.
00243  * This is a utility method which can be used on clients to decompress compressed
00244  * image payload. Since every time a new decompressor is created and deleted
00245  * this method can be slower compared to decompressing the data directly in your
00246  * application so use with care.
00247  * @param yuv422_planar_buffer an already allocated buffer where the decompressed image
00248  * will be stored.
00249  * @param buffer_size size of yuv422_planar_buffer in bytes. Must be big enough to store
00250  * a YUV422_PLANAR image of the image dimensions of the compressed data.
00251  */
00252 void
00253 FuseImageContent::decompress(unsigned char *yuv422_planar_buffer, size_t buffer_size)
00254 {
00255   if ( buffer_size < colorspace_buffer_size(YUV422_PLANAR, ntohs(__header->width),
00256                                             ntohs(__header->height)) ) {
00257     throw fawkes::IllegalArgumentException("Supplied buffer is too small\n");
00258   }
00259   if ( __header->format != FUSE_IF_JPEG ) {
00260     JpegImageDecompressor *decompressor = new JpegImageDecompressor();
00261     decompressor->set_compressed_buffer(__buffer, __buffer_size);
00262     decompressor->set_decompressed_buffer(yuv422_planar_buffer, buffer_size);
00263     decompressor->decompress();
00264     delete decompressor;
00265   } else {
00266     convert((colorspace_t)ntohs(__header->colorspace), YUV422_PLANAR,
00267             __buffer, yuv422_planar_buffer,
00268             ntohs(__header->width), ntohs(__header->height));
00269   }
00270 }
00271 
00272 } // end namespace firevision

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1