19 #include "visiontransfer/imageset.h"
24 #include <arpa/inet.h>
27 using namespace visiontransfer;
29 namespace visiontransfer {
33 class ImageSet::Pimpl {
40 Pimpl(
const Pimpl& other);
43 Pimpl& operator= (Pimpl
const& other);
51 rowStride[imageNumber] = stride;
56 formats[imageNumber] = format;
59 void setPixelData(
int imageNumber,
unsigned char* pixelData) {
61 data[imageNumber] = pixelData;
74 timeMicrosec = microsec;
78 minDisparity = minimum;
79 maxDisparity = maximum;
83 subpixelFactor = subpixFact;
86 void setImageDisparityPair(
bool dispPair);
94 return rowStride[imageNumber];
104 return formats[imageNumber];
114 return data[imageNumber];
130 microsec = timeMicrosec;
134 minimum = minDisparity;
135 maximum = maxDisparity;
139 return subpixelFactor;
142 void writePgmFile(
int imageNumber,
const char* fileName)
const;
144 void copyTo(ImageSet::Pimpl& dest);
162 return numberOfImages;
166 assert(number >= 1 && number <= ImageSet::MAX_SUPPORTED_IMAGES);
167 numberOfImages = number;
180 #ifdef CV_MAJOR_VERSION
195 inline void toOpenCVImage(
int imageNumber, cv::Mat& dest,
bool convertRgbToBgr =
true);
199 exposureTime = timeMicrosec;
207 lastSyncPulseSec = seconds;
208 lastSyncPulseMicrosec = microsec;
212 seconds = lastSyncPulseSec;
213 microsec = lastSyncPulseMicrosec;
219 int rowStride[ImageSet::MAX_SUPPORTED_IMAGES];
220 ImageFormat formats[ImageSet::MAX_SUPPORTED_IMAGES];
221 unsigned char* data[ImageSet::MAX_SUPPORTED_IMAGES];
222 const float* qMatrix;
229 int* referenceCounter;
234 int indexDisparityImage;
238 int lastSyncPulseSec;
239 int lastSyncPulseMicrosec;
241 void copyData(ImageSet::Pimpl& dest,
const ImageSet::Pimpl& src,
bool countRef);
242 void decrementReference();
246 ImageSet::Pimpl::Pimpl()
247 : width(0), height(0), qMatrix(NULL), timeSec(0), timeMicrosec(0),
248 seqNum(0), minDisparity(0), maxDisparity(0), subpixelFactor(16),
249 referenceCounter(NULL), numberOfImages(2), indexLeftImage(0), indexRightImage(1), indexDisparityImage(-1),
250 indexColorImage(-1), exposureTime(0), lastSyncPulseSec(0), lastSyncPulseMicrosec(0) {
251 for (
int i=0; i<ImageSet::MAX_SUPPORTED_IMAGES; ++i) {
258 ImageSet::Pimpl::Pimpl(
const ImageSet::Pimpl& other) {
259 copyData(*
this, other,
true);
262 ImageSet::Pimpl& ImageSet::Pimpl::operator= (ImageSet::Pimpl
const& other) {
264 decrementReference();
265 copyData(*
this, other,
true);
270 ImageSet::Pimpl::~Pimpl() {
271 decrementReference();
274 void ImageSet::Pimpl::copyData(ImageSet::Pimpl& dest,
const ImageSet::Pimpl& src,
bool countRef) {
275 dest.width = src.width;
276 dest.height = src.height;
278 dest.numberOfImages = src.numberOfImages;
279 for(
int i=0; i<ImageSet::MAX_SUPPORTED_IMAGES; i++) {
280 dest.rowStride[i] = src.rowStride[i];
281 dest.formats[i] = src.formats[i];
282 dest.data[i] = src.data[i];
285 dest.qMatrix = src.qMatrix;
286 dest.timeSec = src.timeSec;
287 dest.timeMicrosec = src.timeMicrosec;
288 dest.seqNum = src.seqNum;
289 dest.minDisparity = src.minDisparity;
290 dest.maxDisparity = src.maxDisparity;
291 dest.subpixelFactor = src.subpixelFactor;
292 dest.referenceCounter = src.referenceCounter;
293 dest.numberOfImages = src.numberOfImages;
294 dest.indexLeftImage = src.indexLeftImage;
295 dest.indexRightImage = src.indexRightImage;
296 dest.indexDisparityImage = src.indexDisparityImage;
297 dest.indexColorImage = src.indexColorImage;
298 dest.exposureTime = src.exposureTime;
299 dest.lastSyncPulseSec = src.lastSyncPulseSec;
300 dest.lastSyncPulseMicrosec = src.lastSyncPulseMicrosec;
302 if(dest.referenceCounter !=
nullptr && countRef) {
303 (*dest.referenceCounter)++;
307 void ImageSet::Pimpl::decrementReference() {
308 if(referenceCounter !=
nullptr && --(*referenceCounter) == 0) {
309 for (
int i=0; i<getNumberOfImages(); ++i) {
314 delete referenceCounter;
317 referenceCounter =
nullptr;
321 void ImageSet::Pimpl::writePgmFile(
int imageNumber,
const char* fileName)
const {
322 if(imageNumber < 0 || imageNumber >= getNumberOfImages()) {
323 throw std::runtime_error(
"Illegal image number!");
326 std::fstream strm(fileName, std::ios::out | std::ios::binary);
329 int type, maxVal, bytesPerChannel, channels;
330 switch(formats[imageNumber]) {
350 throw std::runtime_error(
"Illegal pixel format!");
353 strm <<
"P" << type <<
" " << width <<
" " << height <<
" " << maxVal << std::endl;
356 for(
int y = 0; y < height; y++) {
357 for(
int x = 0; x < width*channels; x++) {
358 unsigned char* pixel = &data[imageNumber][y*rowStride[imageNumber] + x*bytesPerChannel];
359 if(bytesPerChannel == 2) {
361 unsigned short swapped = htons(*
reinterpret_cast<unsigned short*
>(pixel));
362 strm.write(
reinterpret_cast<char*
>(&swapped),
sizeof(swapped));
364 strm.write(
reinterpret_cast<char*
>(pixel), 1);
370 void ImageSet::Pimpl::copyTo(ImageSet::Pimpl& dest) {
371 dest.decrementReference();
372 copyData(dest, *
this,
false);
374 dest.qMatrix =
new float[16];
375 memcpy(
const_cast<float*
>(dest.qMatrix), qMatrix,
sizeof(
float)*16);
377 for(
int i=0; i<getNumberOfImages(); i++) {
378 int bytesPixel = getBytesPerPixel(i);
380 dest.rowStride[i] = width*bytesPixel;
381 dest.data[i] =
new unsigned char[height*dest.rowStride[i]];
384 for(
int y = 0; y < height; y++) {
385 memcpy(&dest.data[i][y*dest.rowStride[i]], &data[i][y*rowStride[i]],
390 dest.referenceCounter =
new int;
391 (*dest.referenceCounter) = 1;
395 assert(imageNumber >= 0 && imageNumber < getNumberOfImages());
396 if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_LEFT))
return ImageSet::ImageType::IMAGE_LEFT;
397 if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_RIGHT))
return ImageSet::ImageType::IMAGE_RIGHT;
398 if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_DISPARITY))
return ImageSet::ImageType::IMAGE_DISPARITY;
399 if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_COLOR))
return ImageSet::ImageType::IMAGE_COLOR;
400 throw std::runtime_error(
"Invalid image number for getImageType!");
403 void ImageSet::Pimpl::setImageDisparityPair(
bool dispPair) {
404 if (getNumberOfImages() != 2)
throw std::runtime_error(
"setImageDisparityPair is only supported for two-image sets");
407 indexRightImage = dispPair ? -1 : 1;
408 indexDisparityImage = dispPair ? 1 : -1;
411 int ImageSet::Pimpl::getIndexOf(ImageType what,
bool throwIfNotFound)
const {
414 case ImageSet::IMAGE_LEFT: {
415 idx = indexLeftImage;
418 case ImageSet::IMAGE_RIGHT: {
419 idx = indexRightImage;
422 case ImageSet::IMAGE_DISPARITY: {
423 idx = indexDisparityImage;
427 idx = indexColorImage;
431 throw std::runtime_error(
"Invalid ImageType for query!");
433 if (throwIfNotFound && (idx==-1))
throw std::runtime_error(
"ImageSet does not contain the queried ImageType");
437 void ImageSet::Pimpl::setIndexOf(ImageType what,
int idx) {
439 case ImageSet::IMAGE_LEFT: {
440 indexLeftImage = idx;
443 case ImageSet::IMAGE_RIGHT: {
444 indexRightImage = idx;
447 case ImageSet::IMAGE_DISPARITY: {
448 indexDisparityImage = idx;
452 indexColorImage = idx;
456 throw std::runtime_error(
"Invalid ImageType for setIndexOf!");
472 : pimpl(new Pimpl(*(other.pimpl))) {
476 ImageSet::~ImageSet() {
481 (*pimpl) = *(other.pimpl);
494 pimpl->setRowStride(imageNumber, stride);
498 pimpl->setPixelFormat(imageNumber, format);
502 pimpl->setPixelData(imageNumber, pixelData);
506 pimpl->setQMatrix(q);
510 pimpl->setSequenceNumber(num);
514 pimpl->setTimestamp(seconds, microsec);
518 pimpl->setDisparityRange(minimum, maximum);
522 pimpl->setSubpixelFactor(subpixFact);
525 void ImageSet::setImageDisparityPair(
bool dispPair) {
526 pimpl->setImageDisparityPair(dispPair);
530 return pimpl->getWidth();
534 return pimpl->getHeight();
538 return pimpl->getRowStride(imageNumber);
542 return pimpl->getRowStride(what);
546 return pimpl->getPixelFormat(imageNumber);
550 return pimpl->getPixelFormat(what);
554 return pimpl->getPixelData(imageNumber);
558 return pimpl->getPixelData(what);
562 return pimpl->getQMatrix();
566 return pimpl->getSequenceNumber();
570 pimpl->getTimestamp(seconds, microsec);
574 pimpl->getDisparityRange(minimum, maximum);
578 return pimpl->getSubpixelFactor();
582 pimpl->writePgmFile(imageNumber, fileName);
586 pimpl->copyTo(*(dest.pimpl));
590 return pimpl->getBytesPerPixel(imageNumber);
594 return pimpl->getBitsPerPixel(imageNumber);
598 return pimpl->getBitsPerPixel(what);
602 return pimpl->getNumberOfImages();
606 pimpl->setNumberOfImages(number);
610 return pimpl->getImageType(imageNumber);
614 return pimpl->getIndexOf(what, throwIfNotFound);
618 return pimpl->hasImageType(what);
622 pimpl->setIndexOf(what, idx);
625 #ifdef CV_MAJOR_VERSION
627 pimpl->toOpenCVImage(imageNumber, dest, convertRgbToBgr);
632 pimpl->setExposureTime(timeMicrosec);
636 return pimpl->getExposureTime();
640 pimpl->setLastSyncPulse(seconds, microsec);
644 pimpl->getLastSyncPulse(seconds, microsec);
653 default:
throw std::runtime_error(
"Invalid image format!");
663 default:
throw std::runtime_error(
"Invalid image format!");