1 /*
2 #
3 #  File        : cvMat.h
4 #                ( C++ header file - CImg plug-in )
5 #
6 #  Description : CImg plug-in providing the CImg->cvMat and cvMat->CImg
7 #                conversions for generic image types
8 #                ( IPL = Intel Performance Library )
9 #                This file is a part of the CImg Library project.
10 #                ( http://cimg.eu )
11 #
12 #  Copyright   : Alberto Albiol
13 #                alalbiol@iteam.upv.es
14 #
15 #  How to use  : In the main program include:
16 #   OPENCV 2.4.x
17 #        #include "cv.h"
18 #        #include "highgui.h"
19 #        #define cimg_plugin1 "cvMat.h"
20 #        #include "CImg.h"
21 #
22 #   OPENCV 3.x.x
23 #        #include <opencv2/core.hpp>
24 #        #define cimg_plugin1 "cvMat.h"
25 #        #include "CImg.h"
26 
27 */
28 #ifndef cimg_plugin_cvMat
29 #define cimg_plugin_cvMat
30 
31 // Conversion IPL -> CImg (constructor)
CImg(const cv::Mat & src)32 CImg(const cv::Mat& src):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
33   assign(src);
34 }
35 
36 // Conversion IPL -> CImg (in-place constructor)
assign(const cv::Mat & src)37 CImg<T>& assign(const cv::Mat & src) {
38   if (src.isContinuous()) {
39     switch (src.depth()) {
40         // case CV_1U: { // 1-bit int
41         //    IplImage *src1 = cvCreateImage(cvGetSize(src),CV_8U,1);
42         //    cvConvert(src,src1);
43         //    CImg<ucharT>((unsigned char*)src1->imageData,src1->nChannels,src1.cols,src1.rows,1,true).
44         //      get_permute_axes("yzcx").move_to(*this);
45         //    cvReleaseImage(&src1);
46         //  } break;
47     case CV_8U: // 8-bit unsigned int
48       if (src.channels()==1) {
49         CImg<ucharT>((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
50       } else {
51         std::vector<cv::Mat> channels;
52         cv::split(src,channels);
53         CImg<ucharT>
54           tmp(src.cols,src.rows,1,3),
55           R = tmp.get_shared_channel(2),
56           G = tmp.get_shared_channel(1),
57           B = tmp.get_shared_channel(0);
58         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(uchar));
59         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(uchar));
60         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(uchar));
61         tmp.move_to(*this);
62       }
63       break;
64     case CV_8S: // 8-bit signed int
65       if (src.channels()==1) {
66         CImg<charT>((char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
67       } else {
68         std::vector<cv::Mat> channels;
69         cv::split(src,channels);
70         CImg<ucharT>
71           tmp(src.cols,src.rows,1,3),
72           R = tmp.get_shared_channel(2),
73           G = tmp.get_shared_channel(1),
74           B = tmp.get_shared_channel(0);
75         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(char));
76         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(char));
77         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(char));
78         tmp.move_to(*this);
79       }
80       break;
81     case CV_16U: // 16-bit unsigned int
82       if (src.channels()==1) {
83         CImg<ushortT>((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
84       } else {
85         std::vector<cv::Mat> channels;
86         cv::split(src,channels);
87         CImg<ushortT>
88           tmp(src.cols,src.rows,1,3),
89           R = tmp.get_shared_channel(2),
90           G = tmp.get_shared_channel(1),
91           B = tmp.get_shared_channel(0);
92         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(unsigned short));
93         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(unsigned short));
94         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(unsigned short));
95         tmp.move_to(*this);
96       }
97       break;
98     case CV_16S: // 16-bit signed int
99       if (src.channels()==1) {
100         CImg<shortT>((short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
101       } else {
102         std::vector<cv::Mat> channels;
103         cv::split(src,channels);
104         CImg<shortT>
105           tmp(src.cols,src.rows,1,3),
106           R = tmp.get_shared_channel(2),
107           G = tmp.get_shared_channel(1),
108           B = tmp.get_shared_channel(0);
109         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(short));
110         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(short));
111         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(short));
112         tmp.move_to(*this);
113       }
114       break;
115     case CV_32S: // 32-bit signed int
116       if (src.channels()==1) {
117         CImg<intT>((int*)src.ptr(),src.cols,src.rows,true).move_to(*this);
118       } else {
119         std::vector<cv::Mat> channels;
120         cv::split(src,channels);
121         CImg<intT>
122           tmp(src.cols,src.rows,1,3),
123           R = tmp.get_shared_channel(2),
124           G = tmp.get_shared_channel(1),
125           B = tmp.get_shared_channel(0);
126         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(int));
127         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(int));
128         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(int));
129         tmp.move_to(*this);
130       }
131       break;
132     case CV_32F: // 32-bit float
133       if (src.channels()==1) {
134         CImg<floatT>((float*)src.ptr(),src.cols,src.rows,true).move_to(*this);
135       } else {
136         std::vector<cv::Mat> channels;
137         cv::split(src,channels);
138         CImg<floatT>
139           tmp(src.cols,src.rows,1,3),
140           R = tmp.get_shared_channel(2),
141           G = tmp.get_shared_channel(1),
142           B = tmp.get_shared_channel(0);
143         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(float));
144         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(float));
145         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(float));
146         tmp.move_to(*this);
147       }
148       break;
149     case CV_64F: // 64-bit double
150       if (src.channels()==1) {
151         CImg<doubleT>((double*)src.ptr(),src.cols,src.rows,true).move_to(*this);
152       } else {
153         std::vector<cv::Mat> channels;
154         cv::split(src,channels);
155         CImg<doubleT>
156           tmp(src.cols,src.rows,1,3),
157           R = tmp.get_shared_channel(2),
158           G = tmp.get_shared_channel(1),
159           B = tmp.get_shared_channel(0);
160         std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(double));
161         std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(double));
162         std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(double));
163         tmp.move_to(*this);
164       }
165       break;
166     default:
167       throw CImgInstanceException(_cimg_instance
168                                   "assign(const cv::Mat&) : Mat depth is invalid.",
169                                   cimg_instance);
170       break;
171     }
172   } else {
173     cv::Size size = src.size();
174     switch (src.depth()) {
175     case CV_8U: // 8-bit unsigned int
176       if (src.channels()==1) {
177         CImg<ucharT> tmp(src.cols,src.rows);
178         for (int i = 0; i<size.height; ++i) {
179           const unsigned char* row_i = src.ptr<unsigned char>(i);
180           unsigned char *row_o = tmp.data(0,i);
181           std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
182         }
183         tmp.move_to(*this);
184       } else {
185         CImg<ucharT> tmp(src.cols,src.rows,1,src.channels());
186         std::vector<cv::Mat> channels;
187         cv::split(src,channels);
188         for (int c = 0; c<src.channels(); ++c) {
189           CImg<ucharT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
190           for (int i = 0; i<size.height; ++i) {
191             const unsigned char* row_i = channels[c].ptr<unsigned char>(i);
192             unsigned char *row_o = plane.data(0,i);
193             std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
194           }
195         }
196         tmp.move_to(*this);
197       }
198       break;
199     case CV_8S: // 8-bit int
200       if (src.channels()==1) {
201         CImg<charT> tmp(src.cols,src.rows);
202         for (int i = 0; i<size.height; ++i) {
203           const char* row_i = src.ptr<char>(i);
204           char* row_o = tmp.data(0,i);
205           std::memcpy(row_o,row_i,size.width*sizeof(charT));
206         }
207         tmp.move_to(*this);
208       } else {
209         CImg<charT> tmp(src.cols,src.rows,1,src.channels());
210         std::vector<cv::Mat> channels;
211         cv::split(src,channels);
212         for (int c = 0; c<src.channels(); ++c) {
213           CImg<charT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
214           for (int i = 0; i<size.height; ++i) {
215             const char* row_i = channels[c].ptr<char>(i);
216             char *row_o = plane.data(0,i);
217             std::memcpy(row_o,row_i,size.width*sizeof(char));
218           }
219         }
220         tmp.move_to(*this);
221       }
222       break;
223     case CV_16S: // 16-bit int
224       if (src.channels()==1) {
225         CImg<shortT> tmp(src.cols,src.rows);
226         for (int i = 0; i<size.height; ++i) {
227           const short* row_i = src.ptr<short>(i);
228           short *row_o = tmp.data(0,i);
229           std::memcpy(row_o,row_i,size.width*sizeof(short));
230         }
231         tmp.move_to(*this);
232       } else {
233         CImg<shortT> tmp(src.cols,src.rows,1,src.channels());
234         std::vector<cv::Mat> channels;
235         cv::split(src,channels);
236         for (int c = 0; c<src.channels(); ++c) {
237           CImg<shortT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
238           for (int i = 0; i<size.height; ++i) {
239             const short* row_i = channels[c].ptr<short>(i);
240             short *row_o = plane.data(0,i);
241             std::memcpy(row_o,row_i,size.width*sizeof(short));
242           }
243         }
244         tmp.move_to(*this);
245       }
246       break;
247     case CV_32F: // 32-bit float
248       if (src.channels()==1) {
249         CImg<floatT> tmp(src.cols,src.rows);
250         for (int i = 0; i<size.height; ++i) {
251           const float* row_i = src.ptr<float>(i);
252           float *row_o = tmp.data(0,i);
253           std::memcpy(row_o,row_i,size.width*sizeof(float));
254         }
255         tmp.move_to(*this);
256       } else {
257         CImg<floatT> tmp(src.cols,src.rows,1,src.channels());
258         std::vector<cv::Mat> channels;
259         cv::split(src,channels);
260         for (int c = 0; c<src.channels(); ++c) {
261           CImg<floatT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
262           for (int i = 0; i<size.height; ++i) {
263             const float* row_i = channels[c].ptr<float>(i);
264             float *row_o = plane.data(0,i);
265             std::memcpy(row_o,row_i,size.width*sizeof(float));
266           }
267         }
268         tmp.move_to(*this);
269       }
270       break;
271     case CV_64F: // 64-bit double
272       if (src.channels()==1) {
273         CImg<doubleT> tmp(src.cols,src.rows);
274         for (int i = 0; i<size.height; ++i) {
275           const double* row_i = src.ptr<double>(i);
276           double *row_o = tmp.data(0,i);
277           std::memcpy(row_o,row_i,size.width*sizeof(double));
278         }
279         tmp.move_to(*this);
280       } else {
281         CImg<doubleT> tmp(src.cols,src.rows,1,src.channels());
282         std::vector<cv::Mat> channels;
283         cv::split(src,channels);
284         for (int c = 0; c<src.channels(); ++c) {
285           CImg<doubleT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
286           for (int i = 0; i<size.height; ++i) {
287             const double* row_i = channels[c].ptr<double>(i);
288             double *row_o = plane.data(0,i);
289             std::memcpy(row_o,row_i,size.width*sizeof(double));
290           }
291         }
292         tmp.move_to(*this);
293       }
294       break;
295     default:
296       throw CImgInstanceException(_cimg_instance
297                                   "assign(const cv::Mat&) : Mat depth is invalid.",
298                                   cimg_instance);
299       break;
300     }
301   }
302 
303   //  if (!std::strcmp(src->channelSeq,"BGR")) mirror('v');
304   //  else if (!std::strcmp(src->channelSeq,"BGRA")) get_shared_channels(0,2).mirror('v');
305   return *this;
306 }
307 
308 // Conversion CImg -> MAT
309 cv::Mat get_MAT(const unsigned int z=0) const {
310   if (is_empty())
311     throw CImgInstanceException(_cimg_instance
312                                 "get_MAT() : instance image is empty.",
313                                 cimg_instance);
314   if (z>=_depth)
315     throw CImgInstanceException(_cimg_instance
316                                 "get_MAT() : specified slice %u is out of image bounds.",
317                                 cimg_instance,z);
318   const CImg<T>
319     _slice = _depth>1?get_slice(z):CImg<T>(),
320     &slice = _depth>1?_slice:*this;
321   CImg<T> buf(slice,true);
322   int
323     cols = buf.width(),
324     rows = buf.height(),
325     nchannels = buf.spectrum(),
326     matType=-1;
327 
328   if (!cimg::strcasecmp(buf.pixel_type(),"unsigned char")) matType = CV_8UC1;
329   if (!cimg::strcasecmp(buf.pixel_type(),"char")) matType = CV_8SC1;
330   if (!cimg::strcasecmp(buf.pixel_type(),"unsigned short")) matType = CV_16UC1;
331   if (!cimg::strcasecmp(buf.pixel_type(),"short")) matType = CV_16SC1;
332   if (!cimg::strcasecmp(buf.pixel_type(),"int")) matType = CV_32SC1;
333   if (!cimg::strcasecmp(buf.pixel_type(),"float")) matType = CV_32FC1;
334   if (!cimg::strcasecmp(buf.pixel_type(),"double")) matType = CV_64FC1;
335   if (matType<0)
336     throw CImgInstanceException(_cimg_instance
337                                 "get_MAT() : pixel type '%s' is not supported.",
338                                 cimg_instance,buf.pixel_type());
339   cv::Mat out;
340   std::vector<cv::Mat> channels(nchannels);
341   if (nchannels>1) {
342     for (int c = 0; c<nchannels; ++c) {
343       channels[c] = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data() + rows*cols*(nchannels - 1 - c)));
344     } // for channels
345     cv::merge(channels,out);
346   } else out = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data())).clone();
347   return out;
348 }
349 
350 #endif /* cimg_plugin_cvMat */
351