mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
351 lines
13 KiB
C
351 lines
13 KiB
C
|
/*
|
||
|
#
|
||
|
# File : cvMat.h
|
||
|
# ( C++ header file - CImg plug-in )
|
||
|
#
|
||
|
# Description : CImg plug-in providing the CImg->cvMat and cvMat->CImg
|
||
|
# conversions for generic image types
|
||
|
# ( IPL = Intel Performance Library )
|
||
|
# This file is a part of the CImg Library project.
|
||
|
# ( http://cimg.eu )
|
||
|
#
|
||
|
# Copyright : Alberto Albiol
|
||
|
# alalbiol@iteam.upv.es
|
||
|
#
|
||
|
# How to use : In the main program include:
|
||
|
# OPENCV 2.4.x
|
||
|
# #include "cv.h"
|
||
|
# #include "highgui.h"
|
||
|
# #define cimg_plugin1 "cvMat.h"
|
||
|
# #include "CImg.h"
|
||
|
#
|
||
|
# OPENCV 3.x.x
|
||
|
# #include <opencv2/core.hpp>
|
||
|
# #define cimg_plugin1 "cvMat.h"
|
||
|
# #include "CImg.h"
|
||
|
|
||
|
*/
|
||
|
#ifndef cimg_plugin_cvMat
|
||
|
#define cimg_plugin_cvMat
|
||
|
|
||
|
// Conversion IPL -> CImg (constructor)
|
||
|
CImg(const cv::Mat& src):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
|
||
|
assign(src);
|
||
|
}
|
||
|
|
||
|
// Conversion IPL -> CImg (in-place constructor)
|
||
|
CImg<T>& assign(const cv::Mat & src) {
|
||
|
if (src.isContinuous()) {
|
||
|
switch (src.depth()) {
|
||
|
// case CV_1U: { // 1-bit int
|
||
|
// IplImage *src1 = cvCreateImage(cvGetSize(src),CV_8U,1);
|
||
|
// cvConvert(src,src1);
|
||
|
// CImg<ucharT>((unsigned char*)src1->imageData,src1->nChannels,src1.cols,src1.rows,1,true).
|
||
|
// get_permute_axes("yzcx").move_to(*this);
|
||
|
// cvReleaseImage(&src1);
|
||
|
// } break;
|
||
|
case CV_8U: // 8-bit unsigned int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<ucharT>((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<ucharT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(uchar));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(uchar));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(uchar));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_8S: // 8-bit signed int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<charT>((char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<ucharT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(char));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(char));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(char));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_16U: // 16-bit unsigned int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<ushortT>((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<ushortT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(unsigned short));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(unsigned short));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(unsigned short));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_16S: // 16-bit signed int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<shortT>((short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<shortT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(short));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(short));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(short));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_32S: // 32-bit signed int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<intT>((int*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<intT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(int));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(int));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(int));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_32F: // 32-bit float
|
||
|
if (src.channels()==1) {
|
||
|
CImg<floatT>((float*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<floatT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(float));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(float));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(float));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_64F: // 64-bit double
|
||
|
if (src.channels()==1) {
|
||
|
CImg<doubleT>((double*)src.ptr(),src.cols,src.rows,true).move_to(*this);
|
||
|
} else {
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
CImg<doubleT>
|
||
|
tmp(src.cols,src.rows,1,3),
|
||
|
R = tmp.get_shared_channel(2),
|
||
|
G = tmp.get_shared_channel(1),
|
||
|
B = tmp.get_shared_channel(0);
|
||
|
std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(double));
|
||
|
std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(double));
|
||
|
std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(double));
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
throw CImgInstanceException(_cimg_instance
|
||
|
"assign(const cv::Mat&) : Mat depth is invalid.",
|
||
|
cimg_instance);
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
cv::Size size = src.size();
|
||
|
switch (src.depth()) {
|
||
|
case CV_8U: // 8-bit unsigned int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<ucharT> tmp(src.cols,src.rows);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const unsigned char* row_i = src.ptr<unsigned char>(i);
|
||
|
unsigned char *row_o = tmp.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
} else {
|
||
|
CImg<ucharT> tmp(src.cols,src.rows,1,src.channels());
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
for (int c = 0; c<src.channels(); ++c) {
|
||
|
CImg<ucharT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const unsigned char* row_i = channels[c].ptr<unsigned char>(i);
|
||
|
unsigned char *row_o = plane.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
|
||
|
}
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_8S: // 8-bit int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<charT> tmp(src.cols,src.rows);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const char* row_i = src.ptr<char>(i);
|
||
|
char* row_o = tmp.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(charT));
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
} else {
|
||
|
CImg<charT> tmp(src.cols,src.rows,1,src.channels());
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
for (int c = 0; c<src.channels(); ++c) {
|
||
|
CImg<charT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const char* row_i = channels[c].ptr<char>(i);
|
||
|
char *row_o = plane.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(char));
|
||
|
}
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_16S: // 16-bit int
|
||
|
if (src.channels()==1) {
|
||
|
CImg<shortT> tmp(src.cols,src.rows);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const short* row_i = src.ptr<short>(i);
|
||
|
short *row_o = tmp.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(short));
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
} else {
|
||
|
CImg<shortT> tmp(src.cols,src.rows,1,src.channels());
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
for (int c = 0; c<src.channels(); ++c) {
|
||
|
CImg<shortT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const short* row_i = channels[c].ptr<short>(i);
|
||
|
short *row_o = plane.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(short));
|
||
|
}
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_32F: // 32-bit float
|
||
|
if (src.channels()==1) {
|
||
|
CImg<floatT> tmp(src.cols,src.rows);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const float* row_i = src.ptr<float>(i);
|
||
|
float *row_o = tmp.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(float));
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
} else {
|
||
|
CImg<floatT> tmp(src.cols,src.rows,1,src.channels());
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
for (int c = 0; c<src.channels(); ++c) {
|
||
|
CImg<floatT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const float* row_i = channels[c].ptr<float>(i);
|
||
|
float *row_o = plane.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(float));
|
||
|
}
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
case CV_64F: // 64-bit double
|
||
|
if (src.channels()==1) {
|
||
|
CImg<doubleT> tmp(src.cols,src.rows);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const double* row_i = src.ptr<double>(i);
|
||
|
double *row_o = tmp.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(double));
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
} else {
|
||
|
CImg<doubleT> tmp(src.cols,src.rows,1,src.channels());
|
||
|
std::vector<cv::Mat> channels;
|
||
|
cv::split(src,channels);
|
||
|
for (int c = 0; c<src.channels(); ++c) {
|
||
|
CImg<doubleT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
|
||
|
for (int i = 0; i<size.height; ++i) {
|
||
|
const double* row_i = channels[c].ptr<double>(i);
|
||
|
double *row_o = plane.data(0,i);
|
||
|
std::memcpy(row_o,row_i,size.width*sizeof(double));
|
||
|
}
|
||
|
}
|
||
|
tmp.move_to(*this);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
throw CImgInstanceException(_cimg_instance
|
||
|
"assign(const cv::Mat&) : Mat depth is invalid.",
|
||
|
cimg_instance);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if (!std::strcmp(src->channelSeq,"BGR")) mirror('v');
|
||
|
// else if (!std::strcmp(src->channelSeq,"BGRA")) get_shared_channels(0,2).mirror('v');
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
// Conversion CImg -> MAT
|
||
|
cv::Mat get_MAT(const unsigned int z=0) const {
|
||
|
if (is_empty())
|
||
|
throw CImgInstanceException(_cimg_instance
|
||
|
"get_MAT() : instance image is empty.",
|
||
|
cimg_instance);
|
||
|
if (z>=_depth)
|
||
|
throw CImgInstanceException(_cimg_instance
|
||
|
"get_MAT() : specified slice %u is out of image bounds.",
|
||
|
cimg_instance,z);
|
||
|
const CImg<T>
|
||
|
_slice = _depth>1?get_slice(z):CImg<T>(),
|
||
|
&slice = _depth>1?_slice:*this;
|
||
|
CImg<T> buf(slice,true);
|
||
|
int
|
||
|
cols = buf.width(),
|
||
|
rows = buf.height(),
|
||
|
nchannels = buf.spectrum(),
|
||
|
matType=-1;
|
||
|
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"unsigned char")) matType = CV_8UC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"char")) matType = CV_8SC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"unsigned short")) matType = CV_16UC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"short")) matType = CV_16SC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"int")) matType = CV_32SC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"float")) matType = CV_32FC1;
|
||
|
if (!cimg::strcasecmp(buf.pixel_type(),"double")) matType = CV_64FC1;
|
||
|
if (matType<0)
|
||
|
throw CImgInstanceException(_cimg_instance
|
||
|
"get_MAT() : pixel type '%s' is not supported.",
|
||
|
cimg_instance,buf.pixel_type());
|
||
|
cv::Mat out;
|
||
|
std::vector<cv::Mat> channels(nchannels);
|
||
|
if (nchannels>1) {
|
||
|
for (int c = 0; c<nchannels; ++c) {
|
||
|
channels[c] = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data() + rows*cols*(nchannels - 1 - c)));
|
||
|
} // for channels
|
||
|
cv::merge(channels,out);
|
||
|
} else out = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data())).clone();
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
#endif /* cimg_plugin_cvMat */
|