Fawkes API
Fawkes Development Version
|
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