00001 #include <phEffectsThread.h> 00002 00003 /* ------------------------------------------------------------------------ */ 00004 phEffectsThread::phEffectsThread( phLiveObject *one, 00005 phLiveObject *two, 00006 uint32_t output_format ) 00007 { 00008 phFUNCTION("phEffectsThread::phEffectsThread") 00009 int locked = 0; 00010 00011 phTHIS_LOOSE_LOCK(locked); 00012 00013 this->setName("phEffectsThread"); 00014 this->m_input[0] = (phImage *)one; 00015 this->m_input[1] = (phImage *)two; 00016 this->m_input_count = 2; 00017 #if 0 00018 this->m_alpha = 0.00; 00019 #endif 00020 this->m_output_format = output_format; 00021 00022 this->m_output = new phImage(); 00023 00024 this->m_buf = NULL; 00025 this->m_buf_size = 0; 00026 00027 this->m_resize_width = 90; 00028 this->m_resize_height = 70; 00029 this->m_offset_x = 5; 00030 this->m_offset_y = 45; 00031 00032 phTHIS_LOOSE_UNLOCK(locked); 00033 } 00034 00035 /* ------------------------------------------------------------------------ */ 00036 phEffectsThread::~phEffectsThread() 00037 { 00038 phFree(this->m_buf); 00039 this->m_buf_size = 0; 00040 phDelete(this->m_output); 00041 } 00042 00043 /* ------------------------------------------------------------------------ */ 00044 int phEffectsThread::mosaic_images( phImage *one, phImage *two, phImage *out ) 00045 { 00046 phFUNCTION("phEffectsThread::mosaic_images") 00047 int locked = 0; 00048 uint8_t *ptr[2]; 00049 uint32_t height[2]; 00050 uint32_t width[2]; 00051 uint32_t offset; 00052 uint32_t output_height = 0; 00053 uint32_t output_width = 0; 00054 00055 uint32_t i = 0; 00056 uint32_t j = 0; 00057 00058 uint32_t depth = 0; 00059 00060 if ((one == NULL) || 00061 (two == NULL) || 00062 (one->isNull()) || 00063 (two->isNull())) 00064 { 00065 return phFAIL; 00066 } 00067 00068 phTHIS_LOCK(locked); 00069 00070 /* Convert the input images to one color space */ 00071 rc = one->convert(this->m_output_format); 00072 phPRINT_RC(rc,NULL,"one->convert(%s)", 00073 phImageFormatToString(this->m_output_format)); 00074 00075 rc = two->convert(this->m_output_format); 00076 phPRINT_RC(rc,NULL,"two->convert(%s)", 00077 phImageFormatToString(this->m_output_format)); 00078 00079 /* Make sure our buffer is large enough */ 00080 phDALLOC_RESIZE(this->m_buf, 00081 this->m_buf_size, 00082 one->getSize() + two->getSize(), 00083 uint8_t ); 00084 00085 depth = phImageFormatToDepth(this->m_output_format); 00086 00087 /* Get the pointers to the image only after the conversions */ 00088 ptr[0] = (uint8_t*)one->getImage(); 00089 ptr[1] = (uint8_t*)two->getImage(); 00090 00091 height[0] = one->getHeight(); 00092 height[1] = two->getHeight(); 00093 00094 width[0] = one->getWidth(); 00095 width[1] = two->getWidth(); 00096 00097 output_height = (height[0] > height[1] ? height[0] : height[1]); 00098 output_width = width[0] + width[1]; 00099 00100 offset = 0; 00101 for (j = 0; j < this->m_input_count; j++) 00102 { 00103 for (i = 0; i < height[j]; i++ ) 00104 { 00105 phMemcpy(&(this->m_buf[((i * output_width) + offset) * depth]), 00106 &(ptr[j][i * width[j] * depth]), 00107 width[j] * depth); 00108 } 00109 offset += width[j]; 00110 } 00111 00112 rc = out->setImage(output_width, 00113 output_height, 00114 this->m_output_format, 00115 this->m_buf_size, 00116 this->m_buf); 00117 phCHECK_RC(rc,NULL,"out->setImage"); 00118 00119 phTHIS_UNLOCK(locked); 00120 00121 return phSUCCESS; 00122 error: 00123 00124 phTHIS_ERROR_UNLOCK(locked); 00125 00126 return phFAIL; 00127 } 00128 00129 /* ------------------------------------------------------------------------ */ 00130 int phEffectsThread::overlay_images( phImage *one, phImage *two, 00131 phImage *out ) 00132 { 00133 phFUNCTION("phEffectsThread::overlay_images") 00134 int locked = 0; 00135 00136 float alpha = 0.0; 00137 float alphainv = 0.0; 00138 const int32_t ai = 3; 00139 00140 float tmp = 0; 00141 uint8_t *outptr = NULL; 00142 uint8_t *ptr[2]; 00143 int32_t height[2]; 00144 int32_t width[2]; 00145 int32_t output_width = 0; 00146 int32_t output_height = 0; 00147 int32_t offset_x = 0; 00148 int32_t offset_y = 0; 00149 int32_t offset_remainder_x[2]; 00150 int32_t offset_remainder_y[2]; 00151 int32_t offset_pixel_x[2]; 00152 int32_t offset_pixel_y[2]; 00153 int32_t move_x = 0; 00154 int32_t move_y = 0; 00155 00156 int32_t i = 0; 00157 int32_t j = 0; 00158 int32_t d = 0; 00159 00160 uint32_t depth = 0; 00161 int32_t width_limit = 0; 00162 int32_t height_limit = 0; 00163 00164 if ((one == NULL) || (two == NULL) || (one->isNull()) || (two->isNull())) 00165 { 00166 return phFAIL; 00167 } 00168 00169 phTHIS_LOCK(locked); 00170 00171 move_x = this->m_offset_x; 00172 move_y = this->m_offset_y; 00173 00174 /* Convert the input images to one color space */ 00175 rc = one->convert(this->m_output_format); 00176 phPRINT_RC(rc,NULL,"one->convert(%s)", 00177 phImageFormatToString(this->m_output_format)); 00178 00179 two->resize(this->m_resize_width,this->m_resize_height); 00180 rc = two->convert(this->m_output_format); 00181 phPRINT_RC(rc,NULL,"two->convert(%s)", 00182 phImageFormatToString(this->m_output_format)); 00183 00184 /* 00185 rc = two->resize(one->getWidth(),one->getHeight()); 00186 phPRINT_RC(rc,NULL,"two->resize"); 00187 */ 00188 /* Make sure our buffer is large enough */ 00189 phDALLOC_RESIZE(this->m_buf, 00190 this->m_buf_size, 00191 one->getSize(), 00192 uint8_t ); 00193 00194 depth = phImageFormatToDepth(this->m_output_format); 00195 00196 outptr = this->m_buf; 00197 /* Get the pointers to the image only after the conversions */ 00198 ptr[0] = (uint8_t*)one->getImage(); 00199 ptr[1] = (uint8_t*)two->getImage(); 00200 00201 height[0] = one->getHeight(); 00202 height[1] = two->getHeight(); 00203 00204 width[0] = one->getWidth(); 00205 width[1] = two->getWidth(); 00206 00207 output_width = one->getWidth(); 00208 output_height = one->getHeight(); 00209 00210 /* half width diff == the offset of the X coord of the upper left 00211 * corner of the smaller image within the larger image */ 00212 offset_x = width[0] - width[1]; 00213 if (offset_x > 0) offset_x = offset_x / 2; 00214 00215 /* half height diff == the offset of the Y coord of the upper 00216 * left corner of the smaller image within the larger image */ 00217 offset_y = height[0] - height[1]; 00218 if (offset_y > 0) offset_y = offset_y / 2; 00219 00220 /* The offset pixel is the pixel within the larger image and the 00221 * output image where the overlayed smaller image will start */ 00222 offset_pixel_x[0] = offset_x + move_x; 00223 offset_pixel_y[0] = offset_y + move_y; 00224 offset_remainder_x[0] = offset_x - move_x; 00225 offset_remainder_y[0] = offset_y - move_y; 00226 offset_pixel_y[1] = 0; 00227 offset_pixel_x[1] = 0; 00228 00229 /* if the offset pixel in the larger image is less than 0, we'll 00230 * index into the smaller image instead of the larger image */ 00231 width_limit = width[1]; 00232 if (offset_pixel_x[0] < 0) 00233 { 00234 offset_pixel_x[1] = -1 * offset_pixel_x[0]; 00235 offset_pixel_x[0] = 0; 00236 width_limit -= offset_pixel_x[1]; 00237 offset_remainder_x[1] = width_limit; 00238 } 00239 00240 height_limit = height[1]; 00241 if (offset_pixel_y[0] < 0) 00242 { 00243 offset_pixel_y[1] = -1 * offset_pixel_y[0]; 00244 offset_pixel_y[0] = 0; 00245 height_limit -= offset_pixel_y[1]; 00246 } 00247 00248 /* Copy all the rows of the image that won't have overlayed data into the 00249 * output image buffer */ 00250 phMemcpy(outptr,ptr[0],offset_pixel_y[0] * width[0] * depth); 00251 00252 /* Index into the buffers. 00253 * Index into the larger buffer and output buffer to the row where 00254 * the overlay will begin */ 00255 ptr[0] += offset_pixel_y[0] * width[0] * depth; 00256 ptr[1] += offset_pixel_y[1] * width[1] * depth; 00257 outptr += offset_pixel_y[0] * output_width * depth; 00258 00259 /* This loops over the two input images and overlays them into 00260 * the output image */ 00261 /* we only need to loop through the entirety of the smaller image */ 00262 for (j = 0; j < height_limit; j++) 00263 { 00264 phMemcpy(outptr,ptr[0],offset_pixel_x[0] * 2 * depth); 00265 ptr[0] += (offset_pixel_x[0] * depth); 00266 ptr[1] += (offset_pixel_x[1] * depth); 00267 outptr += (offset_pixel_x[0] * depth); 00268 00269 for (i = 0; i < width_limit; i++ ) 00270 { 00271 /* Read the alpha channel value; This was likely set up in 00272 * the key matte threshold filter. */ 00273 alpha = ((float)ptr[1][ai]) / 255.0; 00274 alphainv = 1.0 - alpha; 00275 00276 for (d = 0; d < 3; d++ ) 00277 { 00278 tmp = ((*ptr[0]) * alphainv) + ((*ptr[1]) * alpha); 00279 if (tmp < 0) tmp = 0; 00280 *outptr = (uint8_t)(tmp > 255 ? 255 : tmp); 00281 ptr[0]++; ptr[1]++; outptr++; 00282 } 00283 00284 outptr++; 00285 ptr[0]++; 00286 ptr[1]++; 00287 } 00288 00289 phMemcpy(outptr,ptr[0],offset_remainder_x[0] * 2 * depth); 00290 ptr[0] += (offset_remainder_x[0] * depth); 00291 outptr += (offset_remainder_x[0] * depth); 00292 } 00293 00294 phMemcpy(outptr,ptr[0],offset_remainder_y[0] * width[0] * depth); 00295 00296 rc = out->setImage(output_width, 00297 output_height, 00298 this->m_output_format, 00299 this->m_buf_size, 00300 this->m_buf); 00301 phCHECK_RC(rc,NULL,"out->setImage"); 00302 00303 phTHIS_UNLOCK(locked); 00304 00305 return phSUCCESS; 00306 error: 00307 00308 phTHIS_ERROR_UNLOCK(locked); 00309 00310 return phFAIL; 00311 } 00312 00313 /* ------------------------------------------------------------------------ */ 00314 int phEffectsThread::run() 00315 { 00316 phFUNCTION("phEffectsThread::run") 00317 phImage local_copy[2]; 00318 uint32_t i = 0; 00319 #if 0 00320 uint32_t counter = 0; 00321 int32_t direction = 1; 00322 #endif 00323 00324 for (i = 0; i < 2; i++ ) 00325 { 00326 rc = local_copy[i].connect(this->m_input[i]); 00327 phCHECK_RC(rc,NULL,"this->local_copy[%d].connect(%p)",i,this->m_input[i]); 00328 } 00329 00330 rc = this->signal_running(); 00331 phCHECK_RC(rc,NULL,"this->signal_running"); 00332 00333 while (this->isRunning()) 00334 { 00335 for (i = 0; i < 2; i++ ) 00336 { 00337 rc = local_copy[i].update(); 00338 phPRINT_RC(rc,NULL,"this->local_copy[%d].update()",i); 00339 } 00340 #if 0 00341 rc = this->mosaic_images(&(local_copy[0]),&(local_copy[1]),this->m_output); 00342 phPRINT_RC(rc,NULL,"this->mosaic_images"); 00343 #else 00344 rc = this->overlay_images(&(local_copy[0]), 00345 &(local_copy[1]), 00346 this->m_output ); 00347 phPRINT_RC(rc,NULL,"this->mosaic_images"); 00348 #endif 00349 00350 #if 0 00351 if (counter == 0) 00352 { 00353 if (this->m_alpha >= 1.00) 00354 direction = -1; 00355 if (this->m_alpha <= 0.00) 00356 direction = 1; 00357 00358 this->m_alpha += 0.1 * direction; 00359 counter = 0; 00360 } 00361 else 00362 { 00363 counter++; 00364 } 00365 #endif 00366 } 00367 00368 for (i = 0; i < 2; i++ ) 00369 { 00370 rc = local_copy[i].disconnect(); 00371 phPRINT_RC(rc,NULL,"this->local_copy[%d].disconnect()",i); 00372 } 00373 00374 return phSUCCESS; 00375 error: 00376 rc = this->signal_error(); 00377 phPRINT_RC(rc,NULL,"this->signal_error"); 00378 00379 return phFAIL; 00380 } 00381 00382 /* ------------------------------------------------------------------------ */ 00383 int phEffectsThread::wakeup() 00384 { 00385 phFUNCTION("phEffectsThread::wakeup") 00386 uint32_t i = 0; 00387 00388 for (i = 0; i < 2; i++ ) 00389 { 00390 rc = this->m_input[i]->wakeup_clients(); 00391 phCHECK_RC(rc,NULL,"this->m_input[%d]->wakeup_clients();",i); 00392 } 00393 00394 return phSUCCESS; 00395 error: 00396 return phFAIL; 00397 } 00398 00399 /* ------------------------------------------------------------------------ */ 00400 int phEffectsThread::setOverlay( int32_t resize_width, int32_t resize_height, 00401 int32_t x, int32_t y ) 00402 { 00403 phFUNCTION("phEffectsThread::setOverlay") 00404 int locked = 0; 00405 00406 phTHIS_LOCK(locked); 00407 00408 this->m_resize_width = resize_width; 00409 this->m_resize_height = resize_height; 00410 this->m_offset_x = x; 00411 this->m_offset_y = y; 00412 00413 phTHIS_UNLOCK(locked); 00414 00415 return phSUCCESS; 00416 error: 00417 00418 phTHIS_ERROR_UNLOCK(locked); 00419 00420 return phFAIL; 00421 } 00422 00423 /* ------------------------------------------------------------------------ */ 00424 int phEffectsThread::getOverlay( int32_t *resize_width, int32_t *resize_height, 00425 int32_t *x, int32_t *y ) 00426 { 00427 phFUNCTION("phEffectsThread::getOverlay") 00428 int locked = 0; 00429 00430 phTHIS_LOCK(locked); 00431 00432 if (resize_width != NULL) *resize_width = this->m_resize_width; 00433 if (resize_height != NULL) *resize_height = this->m_resize_height; 00434 if (x != NULL) *x = this->m_offset_x; 00435 if (y != NULL) *y = this->m_offset_y; 00436 00437 phTHIS_UNLOCK(locked); 00438 00439 return phSUCCESS; 00440 error: 00441 00442 phTHIS_ERROR_UNLOCK(locked); 00443 00444 return phFAIL; 00445 00446 } 00447 00448 /* ------------------------------------------------------------------------ */ 00449 phLiveObject *phEffectsThread::getLiveSourceOutput() 00450 { 00451 return this->m_output; 00452 } 00453 /* ------------------------------------------------------------------------ */ 00454 phLiveObject *phEffectsThread::getOutput() 00455 { 00456 return this->m_output; 00457 }
| Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |
|
1.4.4