1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "precomp.hpp"
43 
44 #include "opencv2/videoio/registry.hpp"
45 #include "videoio_registry.hpp"
46 
47 namespace cv {
48 
49 static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
50 static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
51 static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
52 
53 #define CV_CAPTURE_LOG_DEBUG(tag, ...)                   \
54     if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
55     {                                                    \
56         CV_LOG_WARNING(nullptr, __VA_ARGS__);            \
57     }
58 
59 #define CV_WRITER_LOG_DEBUG(tag, ...)                   \
60     if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
61     {                                                   \
62         CV_LOG_WARNING(nullptr, __VA_ARGS__)            \
63     }
64 
operator ()(CvCapture * obj) const65 void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); }
operator ()(CvVideoWriter * obj) const66 void DefaultDeleter<CvVideoWriter>::operator ()(CvVideoWriter* obj) const { cvReleaseVideoWriter(&obj); }
67 
68 
VideoCapture()69 VideoCapture::VideoCapture() : throwOnFail(false)
70 {}
71 
VideoCapture(const String & filename,int apiPreference)72 VideoCapture::VideoCapture(const String& filename, int apiPreference) : throwOnFail(false)
73 {
74     CV_TRACE_FUNCTION();
75     open(filename, apiPreference);
76 }
77 
VideoCapture(const String & filename,int apiPreference,const std::vector<int> & params)78 VideoCapture::VideoCapture(const String& filename, int apiPreference, const std::vector<int>& params)
79     : throwOnFail(false)
80 {
81     CV_TRACE_FUNCTION();
82     open(filename, apiPreference, params);
83 }
84 
VideoCapture(int index,int apiPreference)85 VideoCapture::VideoCapture(int index, int apiPreference) : throwOnFail(false)
86 {
87     CV_TRACE_FUNCTION();
88     open(index, apiPreference);
89 }
90 
VideoCapture(int index,int apiPreference,const std::vector<int> & params)91 VideoCapture::VideoCapture(int index, int apiPreference, const std::vector<int>& params)
92     : throwOnFail(false)
93 {
94     CV_TRACE_FUNCTION();
95     open(index, apiPreference, params);
96 }
97 
~VideoCapture()98 VideoCapture::~VideoCapture()
99 {
100     CV_TRACE_FUNCTION();
101     icap.release();
102 }
103 
open(const String & filename,int apiPreference)104 bool VideoCapture::open(const String& filename, int apiPreference)
105 {
106     return open(filename, apiPreference, std::vector<int>());
107 }
108 
open(const String & filename,int apiPreference,const std::vector<int> & params)109 bool VideoCapture::open(const String& filename, int apiPreference, const std::vector<int>& params)
110 {
111     CV_INSTRUMENT_REGION();
112 
113     if (isOpened())
114     {
115         release();
116     }
117 
118     const VideoCaptureParameters parameters(params);
119     const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
120     for (size_t i = 0; i < backends.size(); i++)
121     {
122         const VideoBackendInfo& info = backends[i];
123         if (apiPreference == CAP_ANY || apiPreference == info.id)
124         {
125 
126             CV_CAPTURE_LOG_DEBUG(NULL,
127                                  cv::format("VIDEOIO(%s): trying capture filename='%s' ...",
128                                             info.name, filename.c_str()));
129             CV_Assert(!info.backendFactory.empty());
130             const Ptr<IBackend> backend = info.backendFactory->getBackend();
131             if (!backend.empty())
132             {
133                 try
134                 {
135                     icap = backend->createCapture(filename, parameters);
136                     if (!icap.empty())
137                     {
138                         CV_CAPTURE_LOG_DEBUG(NULL,
139                                              cv::format("VIDEOIO(%s): created, isOpened=%d",
140                                                         info.name, icap->isOpened()));
141                         if (icap->isOpened())
142                         {
143                             return true;
144                         }
145                         icap.release();
146                     }
147                     else
148                     {
149                         CV_CAPTURE_LOG_DEBUG(NULL,
150                                              cv::format("VIDEOIO(%s): can't create capture",
151                                                         info.name));
152                     }
153                 }
154                 catch (const cv::Exception& e)
155                 {
156                     if (throwOnFail && apiPreference != CAP_ANY)
157                     {
158                         throw;
159                     }
160                     CV_LOG_ERROR(NULL,
161                                  cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n",
162                                             info.name, e.what()));
163                 }
164                 catch (const std::exception& e)
165                 {
166                     if (throwOnFail && apiPreference != CAP_ANY)
167                     {
168                         throw;
169                     }
170                     CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n",
171                                                   info.name, e.what()));
172                 }
173                 catch (...)
174                 {
175                     if (throwOnFail && apiPreference != CAP_ANY)
176                     {
177                         throw;
178                     }
179                     CV_LOG_ERROR(NULL,
180                                  cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n",
181                                             info.name));
182                 }
183             }
184             else
185             {
186                 CV_CAPTURE_LOG_DEBUG(NULL,
187                                      cv::format("VIDEOIO(%s): backend is not available "
188                                                 "(plugin is missing, or can't be loaded due "
189                                                 "dependencies or it is not compatible)",
190                                                  info.name));
191             }
192         }
193     }
194 
195     if (throwOnFail)
196     {
197         CV_Error_(Error::StsError, ("could not open '%s'", filename.c_str()));
198     }
199 
200     return false;
201 }
202 
open(int cameraNum,int apiPreference)203 bool VideoCapture::open(int cameraNum, int apiPreference)
204 {
205     return open(cameraNum, apiPreference, std::vector<int>());
206 }
207 
open(int cameraNum,int apiPreference,const std::vector<int> & params)208 bool VideoCapture::open(int cameraNum, int apiPreference, const std::vector<int>& params)
209 {
210     CV_TRACE_FUNCTION();
211 
212     if (isOpened())
213     {
214         release();
215     }
216 
217     if (apiPreference == CAP_ANY)
218     {
219         // interpret preferred interface (0 = autodetect)
220         int backendID = (cameraNum / 100) * 100;
221         if (backendID)
222         {
223             cameraNum %= 100;
224             apiPreference = backendID;
225         }
226     }
227 
228     const VideoCaptureParameters parameters(params);
229     const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
230     for (size_t i = 0; i < backends.size(); i++)
231     {
232         const VideoBackendInfo& info = backends[i];
233         if (apiPreference == CAP_ANY || apiPreference == info.id)
234         {
235             CV_CAPTURE_LOG_DEBUG(NULL,
236                                  cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...",
237                                             info.name, cameraNum));
238 
239             CV_Assert(!info.backendFactory.empty());
240             const Ptr<IBackend> backend = info.backendFactory->getBackend();
241             if (!backend.empty())
242             {
243                 try
244                 {
245                     icap = backend->createCapture(cameraNum, parameters);
246                     if (!icap.empty())
247                     {
248                         CV_CAPTURE_LOG_DEBUG(NULL,
249                                              cv::format("VIDEOIO(%s): created, isOpened=%d",
250                                                         info.name, icap->isOpened()));
251                         if (icap->isOpened())
252                         {
253                             return true;
254                         }
255                         icap.release();
256                     }
257                     else
258                     {
259                         CV_CAPTURE_LOG_DEBUG(NULL,
260                                              cv::format("VIDEOIO(%s): can't create capture",
261                                                         info.name));
262                     }
263                 }
264                 catch (const cv::Exception& e)
265                 {
266                     if (throwOnFail && apiPreference != CAP_ANY)
267                     {
268                         throw;
269                     }
270                     CV_LOG_ERROR(NULL,
271                                  cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n",
272                                             info.name, e.what()));
273                 }
274                 catch (const std::exception& e)
275                 {
276                     if (throwOnFail && apiPreference != CAP_ANY)
277                     {
278                         throw;
279                     }
280                     CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n",
281                                                   info.name, e.what()));
282                 }
283                 catch (...)
284                 {
285                     if (throwOnFail && apiPreference != CAP_ANY)
286                     {
287                         throw;
288                     }
289                     CV_LOG_ERROR(NULL,
290                                  cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n",
291                                             info.name));
292                 }
293             }
294             else
295             {
296                 CV_CAPTURE_LOG_DEBUG(NULL,
297                                      cv::format("VIDEOIO(%s): backend is not available "
298                                                 "(plugin is missing, or can't be loaded due "
299                                                 "dependencies or it is not compatible)",
300                                                  info.name));
301             }
302         }
303     }
304 
305     if (throwOnFail)
306     {
307         CV_Error_(Error::StsError, ("could not open camera %d", cameraNum));
308     }
309 
310     return false;
311 }
312 
isOpened() const313 bool VideoCapture::isOpened() const
314 {
315     return !icap.empty() ? icap->isOpened() : false;
316 }
317 
getBackendName() const318 String VideoCapture::getBackendName() const
319 {
320     int api = 0;
321     if (icap)
322     {
323         api = icap->isOpened() ? icap->getCaptureDomain() : 0;
324     }
325     CV_Assert(api != 0);
326     return cv::videoio_registry::getBackendName(static_cast<VideoCaptureAPIs>(api));
327 }
328 
release()329 void VideoCapture::release()
330 {
331     CV_TRACE_FUNCTION();
332     icap.release();
333 }
334 
grab()335 bool VideoCapture::grab()
336 {
337     CV_INSTRUMENT_REGION();
338     bool ret = !icap.empty() ? icap->grabFrame() : false;
339     if (!ret && throwOnFail)
340     {
341         CV_Error(Error::StsError, "");
342     }
343     return ret;
344 }
345 
retrieve(OutputArray image,int channel)346 bool VideoCapture::retrieve(OutputArray image, int channel)
347 {
348     CV_INSTRUMENT_REGION();
349 
350     bool ret = false;
351     if (!icap.empty())
352     {
353         ret = icap->retrieveFrame(channel, image);
354     }
355     if (!ret && throwOnFail)
356     {
357         CV_Error_(Error::StsError, ("could not retrieve channel %d", channel));
358     }
359     return ret;
360 }
361 
read(OutputArray image)362 bool VideoCapture::read(OutputArray image)
363 {
364     CV_INSTRUMENT_REGION();
365 
366     if (grab())
367     {
368         retrieve(image);
369     } else {
370         image.release();
371     }
372     return !image.empty();
373 }
374 
operator >>(Mat & image)375 VideoCapture& VideoCapture::operator >> (Mat& image)
376 {
377 #ifdef WINRT_VIDEO
378     // FIXIT grab/retrieve methods() should work too
379     if (grab())
380     {
381         if (retrieve(image))
382         {
383             std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
384             VideoioBridge& bridge = VideoioBridge::getInstance();
385 
386             // double buffering
387             bridge.swapInputBuffers();
388             auto p = bridge.frontInputPtr;
389 
390             bridge.bIsFrameNew = false;
391 
392             // needed here because setting Mat 'image' is not allowed by OutputArray in read()
393             Mat m(bridge.getHeight(), bridge.getWidth(), CV_8UC3, p);
394             image = m;
395         }
396     }
397 #else
398     read(image);
399 #endif
400     return *this;
401 }
402 
operator >>(UMat & image)403 VideoCapture& VideoCapture::operator >> (UMat& image)
404 {
405     CV_INSTRUMENT_REGION();
406 
407     read(image);
408     return *this;
409 }
410 
set(int propId,double value)411 bool VideoCapture::set(int propId, double value)
412 {
413     CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property");
414     bool ret = !icap.empty() ? icap->setProperty(propId, value) : false;
415     if (!ret && throwOnFail)
416     {
417         CV_Error_(Error::StsError, ("could not set prop %d = %f", propId, value));
418     }
419     return ret;
420 }
421 
get(int propId) const422 double VideoCapture::get(int propId) const
423 {
424     if (propId == CAP_PROP_BACKEND)
425     {
426         int api = 0;
427         if (icap && icap->isOpened())
428         {
429             api = icap->getCaptureDomain();
430         }
431         if (api <= 0)
432         {
433             return -1.0;
434         }
435         return static_cast<double>(api);
436     }
437     return !icap.empty() ? icap->getProperty(propId) : 0;
438 }
439 
440 
waitAny(const std::vector<VideoCapture> & streams,CV_OUT std::vector<int> & readyIndex,int64 timeoutNs)441 bool VideoCapture::waitAny(const std::vector<VideoCapture>& streams,
442                            CV_OUT std::vector<int>& readyIndex, int64 timeoutNs)
443 {
444     CV_Assert(!streams.empty());
445 
446     VideoCaptureAPIs backend = (VideoCaptureAPIs)streams[0].icap->getCaptureDomain();
447 
448     for (size_t i = 1; i < streams.size(); ++i)
449     {
450         VideoCaptureAPIs backend_i = (VideoCaptureAPIs)streams[i].icap->getCaptureDomain();
451         CV_CheckEQ((int)backend, (int)backend_i, "All captures must have the same backend");
452     }
453 
454 #if (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) // see cap_v4l.cpp guard
455     if (backend == CAP_V4L2)
456     {
457         return VideoCapture_V4L_waitAny(streams, readyIndex, timeoutNs);
458     }
459 #else
460     CV_UNUSED(readyIndex);
461     CV_UNUSED(timeoutNs);
462 #endif
463     CV_Error(Error::StsNotImplemented, "VideoCapture::waitAny() is supported by V4L backend only");
464 }
465 
466 
467 //=================================================================================================
468 
469 
470 
VideoWriter()471 VideoWriter::VideoWriter()
472 {}
473 
VideoWriter(const String & filename,int _fourcc,double fps,Size frameSize,bool isColor)474 VideoWriter::VideoWriter(const String& filename, int _fourcc, double fps, Size frameSize,
475                          bool isColor)
476 {
477     open(filename, _fourcc, fps, frameSize, isColor);
478 }
479 
480 
VideoWriter(const String & filename,int apiPreference,int _fourcc,double fps,Size frameSize,bool isColor)481 VideoWriter::VideoWriter(const String& filename, int apiPreference, int _fourcc, double fps,
482                          Size frameSize, bool isColor)
483 {
484     open(filename, apiPreference, _fourcc, fps, frameSize, isColor);
485 }
486 
VideoWriter(const cv::String & filename,int fourcc,double fps,const cv::Size & frameSize,const std::vector<int> & params)487 VideoWriter::VideoWriter(const cv::String& filename, int fourcc, double fps,
488                          const cv::Size& frameSize, const std::vector<int>& params)
489 {
490     open(filename, fourcc, fps, frameSize, params);
491 }
492 
VideoWriter(const cv::String & filename,int apiPreference,int fourcc,double fps,const cv::Size & frameSize,const std::vector<int> & params)493 VideoWriter::VideoWriter(const cv::String& filename, int apiPreference, int fourcc, double fps,
494                          const cv::Size& frameSize, const std::vector<int>& params)
495 {
496     open(filename, apiPreference, fourcc, fps, frameSize, params);
497 }
498 
release()499 void VideoWriter::release()
500 {
501     iwriter.release();
502 }
503 
~VideoWriter()504 VideoWriter::~VideoWriter()
505 {
506     release();
507 }
508 
open(const String & filename,int _fourcc,double fps,Size frameSize,bool isColor)509 bool VideoWriter::open(const String& filename, int _fourcc, double fps, Size frameSize,
510                        bool isColor)
511 {
512     return open(filename, CAP_ANY, _fourcc, fps, frameSize,
513                 std::vector<int> { VIDEOWRITER_PROP_IS_COLOR, static_cast<int>(isColor) });
514 }
515 
open(const String & filename,int apiPreference,int _fourcc,double fps,Size frameSize,bool isColor)516 bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, double fps,
517                        Size frameSize, bool isColor)
518 {
519     return open(filename, apiPreference, _fourcc, fps, frameSize,
520                 std::vector<int> { VIDEOWRITER_PROP_IS_COLOR, static_cast<int>(isColor) });
521 }
522 
523 
open(const String & filename,int fourcc,double fps,const Size & frameSize,const std::vector<int> & params)524 bool VideoWriter::open(const String& filename, int fourcc, double fps, const Size& frameSize,
525                        const std::vector<int>& params)
526 {
527     return open(filename, CAP_ANY, fourcc, fps, frameSize, params);
528 }
529 
open(const String & filename,int apiPreference,int fourcc,double fps,const Size & frameSize,const std::vector<int> & params)530 bool VideoWriter::open(const String& filename, int apiPreference, int fourcc, double fps,
531                        const Size& frameSize, const std::vector<int>& params)
532 {
533     CV_INSTRUMENT_REGION();
534 
535     if (isOpened())
536     {
537         release();
538     }
539 
540     const VideoWriterParameters parameters(params);
541     for (const auto& info : videoio_registry::getAvailableBackends_Writer())
542     {
543         if (apiPreference == CAP_ANY || apiPreference == info.id)
544         {
545             CV_WRITER_LOG_DEBUG(NULL,
546                                 cv::format("VIDEOIO(%s): trying writer with filename='%s' "
547                                            "fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...",
548                                            info.name, filename.c_str(), (unsigned)fourcc, fps,
549                                            frameSize.width, frameSize.height,
550                                            parameters.get(VIDEOWRITER_PROP_IS_COLOR, true)));
551             CV_Assert(!info.backendFactory.empty());
552             const Ptr<IBackend> backend = info.backendFactory->getBackend();
553             if (!backend.empty())
554             {
555                 try
556                 {
557                     iwriter = backend->createWriter(filename, fourcc, fps, frameSize, parameters);
558                     if (!iwriter.empty())
559                     {
560 
561                         CV_WRITER_LOG_DEBUG(NULL,
562                                             cv::format("VIDEOIO(%s): created, isOpened=%d",
563                                                        info.name, iwriter->isOpened()));
564                         if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
565                         {
566                             for (int key: parameters.getUnused())
567                             {
568                                 CV_LOG_WARNING(NULL,
569                                                cv::format("VIDEOIO(%s): parameter with key '%d' was unused",
570                                                           info.name, key));
571                             }
572                         }
573                         if (iwriter->isOpened())
574                         {
575                             return true;
576                         }
577                         iwriter.release();
578                     }
579                     else
580                     {
581                         CV_WRITER_LOG_DEBUG(NULL, cv::format("VIDEOIO(%s): can't create writer",
582                                                              info.name));
583                     }
584                 }
585                 catch (const cv::Exception& e)
586                 {
587                     CV_LOG_ERROR(NULL,
588                                  cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n",
589                                             info.name, e.what()));
590                 }
591                 catch (const std::exception& e)
592                 {
593                     CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n",
594                                                   info.name, e.what()));
595                 }
596                 catch (...)
597                 {
598                     CV_LOG_ERROR(NULL,
599                                  cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n",
600                                             info.name));
601                 }
602             }
603             else
604             {
605                 CV_WRITER_LOG_DEBUG(NULL,
606                                     cv::format("VIDEOIO(%s): backend is not available "
607                                                "(plugin is missing, or can't be loaded due "
608                                                "dependencies or it is not compatible)",
609                                                info.name));
610             }
611         }
612     }
613     return false;
614 }
615 
isOpened() const616 bool VideoWriter::isOpened() const
617 {
618     return !iwriter.empty();
619 }
620 
621 
set(int propId,double value)622 bool VideoWriter::set(int propId, double value)
623 {
624     CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property");
625 
626     if (!iwriter.empty())
627     {
628         return iwriter->setProperty(propId, value);
629     }
630     return false;
631 }
632 
get(int propId) const633 double VideoWriter::get(int propId) const
634 {
635     if (propId == CAP_PROP_BACKEND)
636     {
637         int api = 0;
638         if (iwriter)
639         {
640             api = iwriter->getCaptureDomain();
641         }
642         return (api <= 0) ?  -1. : static_cast<double>(api);
643     }
644     if (!iwriter.empty())
645     {
646         return iwriter->getProperty(propId);
647     }
648     return 0.;
649 }
650 
getBackendName() const651 String VideoWriter::getBackendName() const
652 {
653     int api = 0;
654     if (iwriter)
655     {
656         api = iwriter->getCaptureDomain();
657     }
658     CV_Assert(api != 0);
659     return cv::videoio_registry::getBackendName(static_cast<VideoCaptureAPIs>(api));
660 }
661 
write(InputArray image)662 void VideoWriter::write(InputArray image)
663 {
664     CV_INSTRUMENT_REGION();
665 
666     if (iwriter)
667     {
668         iwriter->write(image);
669     }
670 }
671 
operator <<(const Mat & image)672 VideoWriter& VideoWriter::operator << (const Mat& image)
673 {
674     CV_INSTRUMENT_REGION();
675 
676     write(image);
677     return *this;
678 }
679 
operator <<(const UMat & image)680 VideoWriter& VideoWriter::operator << (const UMat& image)
681 {
682     CV_INSTRUMENT_REGION();
683     write(image);
684     return *this;
685 }
686 
687 // FIXIT OpenCV 4.0: make inline
fourcc(char c1,char c2,char c3,char c4)688 int VideoWriter::fourcc(char c1, char c2, char c3, char c4)
689 {
690     return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24);
691 }
692 
693 } // namespace cv
694