VFWCapture.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00035 // ****************************************************************************
00036 // Filename:  VFWCapture.cpp
00037 // Author:    Pedram Azad
00038 // Date:      2005
00039 // ****************************************************************************
00040 
00041 
00042 // ****************************************************************************
00043 // Includes
00044 // ****************************************************************************
00045 
00046 #include "VFWCapture.h"
00047 
00048 #include "Image/ByteImage.h"
00049 #include "Image/ImageProcessor.h"
00050 #include "Helpers/helpers.h"
00051 
00052 #include <vfw.h>
00053 #include <wingdi.h>
00054 
00055 
00056 // ****************************************************************************
00057 // Defines
00058 // ****************************************************************************
00059 
00060 // FOURCC codes understood by the capture code
00061 #define BI_I420 0x30323449
00062 #define BI_YUY2 0x32595559
00063 
00064 
00065 // ****************************************************************************
00066 // Global and static variables
00067 // ****************************************************************************
00068 
00069 CRITICAL_SECTION critical_section;
00070 static CByteImage *pCapturedImage = 0;
00071 
00072 
00073 // ****************************************************************************
00074 // Static functions
00075 // ****************************************************************************
00076 
00077 #define myClip(x) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (unsigned char) (x))
00078 static inline void yuv2rgb(unsigned char y, unsigned char u, unsigned char v, unsigned char *out)
00079 {
00080         int C = (int) y - 16;
00081         int D = (int) u - 128;
00082         int E = (int) v - 128;
00083 
00084         int R = (( 298 * C + 409 * E + 128) >> 8);
00085         int G = (( 298 * C - 100 * D - 208 * E + 128) >> 8);
00086         int B = (( 298 * C + 516 * D + 128) >> 8);
00087 
00088         out[0] = myClip(R);
00089         out[1] = myClip(G);
00090         out[2] = myClip(B);
00091 }
00092 #undef myClip
00093 
00094 static LRESULT CALLBACK CallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
00095 {
00096         EnterCriticalSection(&critical_section);
00097 
00098         if (!pCapturedImage)
00099         {
00100                 LeaveCriticalSection(&critical_section);
00101                 return (LRESULT) TRUE;
00102         }
00103 
00104         pCapturedImage->pixels = (unsigned char *) lpVHdr->lpData;
00105 
00106         LeaveCriticalSection(&critical_section);
00107 
00108         return (LRESULT) TRUE;
00109 }
00110 
00111 
00112 // ****************************************************************************
00113 // Constructor / Destructor
00114 // ****************************************************************************
00115 
00116 CVFWCapture::CVFWCapture(int nDriverIndex)
00117 {
00118         pCapturedImage = 0;
00119         m_hCaptureWnd = 0;
00120 
00121         m_nWidth = -1;
00122         m_nHeight = -1;
00123         m_nBitsPerPixel = 0;
00124         m_type = CByteImage::eGrayScale;
00125 
00126         m_nDriverIndex = nDriverIndex;
00127         m_bFlipY = false;
00128 
00129         m_bCameraOpened = false;
00130 
00131         for (int i = 0; i < 1024; i++)
00132                 m_clip[i] = i < 256 ? i : 255;
00133 
00134         InitializeCriticalSection(&critical_section);
00135 }
00136 
00137 CVFWCapture::~CVFWCapture()
00138 {
00139         CloseCamera();
00140 
00141         if (m_hCaptureWnd)
00142         {
00143                 DestroyWindow(m_hCaptureWnd);
00144                 m_hCaptureWnd = 0;
00145         }
00146 
00147         if (pCapturedImage)
00148                 delete pCapturedImage;
00149 
00150         DeleteCriticalSection(&critical_section);
00151 }
00152 
00153 
00154 // ****************************************************************************
00155 // Methods
00156 // ****************************************************************************
00157 
00158 bool CVFWCapture::OpenCamera()
00159 {
00160         // prevent multiple init
00161         if (!m_hCaptureWnd)
00162         {
00163                 // init attributes and create capture window
00164                 m_hCaptureWnd = capCreateCaptureWindow("Capture Window", 0, 0, 0, 640, 480, NULL, 0);
00165                 if (!m_hCaptureWnd)
00166                         return false;
00167 
00168                 // set callback function for single frame capturing
00169                 if (!capSetCallbackOnFrame(m_hCaptureWnd, CallbackProc))
00170                 {
00171                         DestroyWindow(m_hCaptureWnd);
00172                         m_hCaptureWnd = 0;
00173                         return false;
00174                 }
00175         }
00176 
00177         // connect to driver
00178         if (!capDriverConnect(m_hCaptureWnd, m_nDriverIndex))
00179         {
00180                 DestroyWindow(m_hCaptureWnd);
00181                 m_hCaptureWnd = 0;
00182                 return false;
00183         }
00184 
00185         UpdateInformation();
00186 
00187         capOverlay(m_hCaptureWnd, FALSE);
00188         capPreview(m_hCaptureWnd, FALSE);
00189 
00190         CAPTUREPARMS s;
00191         s.dwRequestMicroSecPerFrame = 41667;
00192         s.fMakeUserHitOKToCapture = FALSE;
00193         s.wPercentDropForError = 10;
00194         s.fYield = TRUE;
00195         s.dwIndexSize = 34952;
00196         s.wChunkGranularity = 0;
00197         s.fUsingDOSMemory = FALSE;
00198         s.wNumVideoRequested = 10;
00199         s.fCaptureAudio = FALSE;
00200         //s.wNumAudioRequested = 0;
00201         s.vKeyAbort = VK_ESCAPE;
00202         s.fAbortLeftMouse = FALSE;
00203         s.fAbortRightMouse = FALSE;
00204         s.fLimitEnabled = FALSE;
00205         //s.wTimeLimit = 0;
00206         s.fMCIControl = FALSE;
00207         //s.fStepMCIDevice = FALSE;
00208         //s.dwMCIStartTime = 0;
00209         //s.dwMCIStopTime = 0;
00210         s.fStepCaptureAt2x = FALSE;
00211         s.wStepCaptureAverageFrames = 1;
00212         s.dwAudioBufferSize = 0;
00213         s.fDisableWriteCache = FALSE;
00214         s.AVStreamMaster = AVSTREAMMASTER_NONE;
00215 
00216         capCaptureSetSetup(m_hCaptureWnd, &s, sizeof(CAPTUREPARMS));
00217         //capCaptureSequenceNoFile(m_hCaptureWnd);
00218 
00219         m_bCameraOpened = true;
00220         
00221         return true;
00222 }
00223 
00224 void CVFWCapture::CloseCamera()
00225 {
00226         if (m_bCameraOpened)
00227         {
00228                 //capCaptureAbort(m_hCaptureWnd);
00229                 //capCaptureStop(m_hCaptureWnd);
00230                 capDriverDisconnect(m_hCaptureWnd);
00231 
00232                 m_nWidth = 0;
00233                 m_nHeight = 0;
00234                 m_nBitsPerPixel = 0;
00235 
00236                 m_bCameraOpened = false;
00237         }
00238 }
00239 
00240 bool CVFWCapture::GetDriverName(int nDriverIndex, std::string &sName)
00241 {
00242         char szName[1000];
00243         char szVersion[1000];
00244 
00245         if (!capGetDriverDescription(nDriverIndex, szName, sizeof(szName), szVersion, sizeof(szVersion)))
00246                 return false;
00247 
00248         sName = "";
00249         sName += szName;
00250 
00251         return true;
00252 }
00253 
00254 void CVFWCapture::ShowVideoFormatDialog()
00255 {
00256         EnterCriticalSection(&critical_section);
00257 
00258         CAPDRIVERCAPS gCapDriverCaps;
00259 
00260         // get driver information
00261         if (m_hCaptureWnd && capDriverGetCaps(m_hCaptureWnd, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)))
00262         {
00263                 if (gCapDriverCaps.fHasDlgVideoFormat)
00264                 {
00265                         capDlgVideoFormat(m_hCaptureWnd);
00266                         UpdateInformation();
00267                 }
00268         }
00269 
00270         LeaveCriticalSection(&critical_section);
00271 }
00272 
00273 void CVFWCapture::ShowVideoSourceDialog()
00274 {
00275         CAPDRIVERCAPS gCapDriverCaps;
00276 
00277         // get driver information
00278         if (m_hCaptureWnd && capDriverGetCaps(m_hCaptureWnd, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)))
00279         {
00280                 if (gCapDriverCaps.fHasDlgVideoSource)
00281                 {
00282                         capDlgVideoSource(m_hCaptureWnd);
00283                         UpdateInformation();
00284                 }
00285         }
00286 }
00287 
00288 void CVFWCapture::UpdateInformation()
00289 {
00290         EnterCriticalSection(&critical_section);
00291 
00292         BITMAPINFO bitmapInfo;
00293 
00294         if (m_hCaptureWnd && capGetVideoFormat(m_hCaptureWnd, &bitmapInfo, sizeof(BITMAPINFO)))
00295         {
00296                 m_nWidth = bitmapInfo.bmiHeader.biWidth;
00297                 m_nHeight = abs(bitmapInfo.bmiHeader.biHeight);
00298                 m_nBitsPerPixel = bitmapInfo.bmiHeader.biBitCount;
00299                 m_nCompression = bitmapInfo.bmiHeader.biCompression;
00300 
00301                 m_bFlipY = false;
00302 
00303                 // For compressed video and YUV formats, this member is a FOURCC code, specified as a DWORD 
00304                 // in little-endian order. For example, YUYV video has the FOURCC 'VYUY' or 0x56595559. For 
00305                 // more information, see FOURCC Codes.
00306                 // For uncompressed RGB formats, the following values are possible:
00307                 // Value                        Description
00308                 // BI_RGB                       Uncompressed RGB.
00309                 // BI_BITFIELDS         Uncompressed RGB with color masks. Valid for 16-bpp and 32-bpp bitmaps.
00310                 if (m_nCompression != BI_RGB && m_nCompression != BI_BITFIELDS)
00311                 {
00312                         printf("fourcc = %08x (%c%c%c%c)\n", m_nCompression, (m_nCompression >> 0) & 0xff, (m_nCompression >> 8) & 0xff, (m_nCompression >> 16) & 0xff, (m_nCompression >> 24) & 0xff);
00313                         m_type = CByteImage::eRGB24;
00314                 }
00315                 else
00316                 {
00317                         m_type = m_nBitsPerPixel > 8 ? CByteImage::eRGB24 : CByteImage::eGrayScale;
00318                         
00319                         if (bitmapInfo.bmiHeader.biHeight > 0)
00320                         {
00321                                 // image is transmitted bottom-up (vertically flipped)
00322                                 m_bFlipY = true;
00323                         }
00324                 }
00325 
00326                 if (pCapturedImage)
00327                         delete pCapturedImage;
00328                 
00329                 pCapturedImage = new CByteImage(m_nWidth, m_nHeight, m_type, true);
00330         }
00331 
00332         LeaveCriticalSection(&critical_section);
00333 }
00334 
00335 bool CVFWCapture::CaptureImage(CByteImage **ppImages)
00336 {
00337         capGrabFrameNoStop(m_hCaptureWnd);
00338 
00339         EnterCriticalSection(&critical_section);
00340 
00341         // check if input image matches format
00342         if (!m_bCameraOpened || !m_hCaptureWnd || !ppImages || !ppImages[0] || m_nWidth != ppImages[0]->width || m_nHeight != ppImages[0]->height || m_type != ppImages[0]->type)
00343         {
00344                 LeaveCriticalSection(&critical_section);
00345                 return false;
00346         }
00347 
00348         if (pCapturedImage && pCapturedImage->pixels)
00349         {
00350                 if (pCapturedImage->type == CByteImage::eRGB24)
00351                 {
00352                         unsigned char *output = ppImages[0]->pixels;
00353 
00354                         if (m_nCompression == BI_RGB)
00355                         {
00356                                 if (m_nBitsPerPixel == 24)
00357                                 {
00358                                         const int nBytes = m_nWidth * m_nHeight * 3;
00359                                         const unsigned char *input = pCapturedImage->pixels;
00360 
00361                                         for (int i = 0; i < nBytes; i += 3)
00362                                         {
00363                                                 output[i] = input[i + 2];
00364                                                 output[i + 1] = input[i + 1];
00365                                                 output[i + 2] = input[i];
00366                                         }
00367                                 }
00368                         }
00369                         else if (m_nCompression == BI_BITFIELDS)
00370                         {
00371                                 printf("error: BI_BITFIELDS not yet implemented\n");
00372                         }
00373                         else
00374                         {
00375                                 // thanks to Paul van Niekerk
00376                                 if (m_nCompression == BI_I420)
00377                                 {
00378                                         const int nBytes = m_nWidth * m_nHeight;
00379                                         const unsigned char *inputY = pCapturedImage->pixels;
00380                                         const unsigned char *inputU = inputY + nBytes;
00381                                         const unsigned char *inputV = inputU + nBytes / 4;
00382 
00383                                         int i = 0;
00384                                         for (int h = 0; h < m_nHeight; h += 1)
00385                                         {
00386                                                 for (int w = 0; w < m_nWidth; w += 1)
00387                                                 {
00388                                                         int j = (h / 2) * (m_nWidth / 2) + (w / 2);
00389                                                         yuv2rgb(inputY[i], inputU[j], inputV[j], &output[3 * i]);
00390                                                         i += 1;
00391                                                 }
00392                                         }
00393                                 }
00394                                 else if (m_nCompression == BI_YUY2)
00395                                 {
00396                                         const int nBytes = m_nWidth * m_nHeight * 2;
00397                                         const unsigned char *input = pCapturedImage->pixels;
00398 
00399                                         for (int i = 0; i < nBytes; i += 4)
00400                                         {
00401                                                 unsigned char y0 = *input++;
00402                                                 unsigned char u = *input++;
00403                                                 unsigned char y1 = *input++;
00404                                                 unsigned char v = *input++;
00405 
00406                                                 yuv2rgb(y0, u, v, output);
00407                                                 output += 3;
00408                                                 yuv2rgb(y1, u, v, output);
00409                                                 output += 3;
00410                                         }
00411                                 }
00412                         }
00413                 }
00414                 else
00415                         ImageProcessor::CopyImage(pCapturedImage, ppImages[0]);
00416         }
00417 
00418         LeaveCriticalSection(&critical_section);
00419 
00420         if (m_bFlipY)
00421                 ImageProcessor::FlipY(ppImages[0], ppImages[0]);
00422 
00423         return true;
00424 }
00425 
00426 #undef BI_I420
00427 #undef BI_YUY2


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:58