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

phEffectsThread.cpp

Go to the documentation of this file.
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
SourceForge.net Logo

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