libvisiontransfer  6.4.0
imagepair.cpp
1 /*******************************************************************************
2  * Copyright (c) 2019 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #include <iostream>
16 #include <fstream>
17 #include <stdexcept>
18 #include <cstring>
19 #include "visiontransfer/imagepair.h"
20 
21 #ifdef _WIN32
22 #include <winsock2.h>
23 #else
24 #include <arpa/inet.h>
25 #endif
26 
27 using namespace visiontransfer;
28 
30  : width(0), height(0), qMatrix(NULL), timeSec(0), timeMicrosec(0),
31  seqNum(0), minDisparity(0), maxDisparity(0), disparityPair(false),
32  referenceCounter(NULL) {
33  formats[0] = FORMAT_8_BIT_MONO;
34  formats[1] = FORMAT_8_BIT_MONO;
35  data[0] = NULL;
36  data[1] = NULL;
37  rowStride[0] = 0;
38  rowStride[1] = 1;
39 }
40 
42  copyData(*this, other, true);
43 }
44 
45 ImagePair& ImagePair::operator= (ImagePair const& other) {
46  if(&other != this) {
47  decrementReference();
48  copyData(*this, other, true);
49  }
50  return *this;
51 }
52 
53 ImagePair::~ImagePair() {
54  decrementReference();
55 }
56 
57 void ImagePair::copyData(ImagePair& dest, const ImagePair& src, bool countRef) {
58  dest.width = src.width;
59  dest.height = src.height;
60 
61  for(int i=0; i<2; i++) {
62  dest.rowStride[i] = src.rowStride[i];
63  dest.formats[i] = src.formats[i];
64  dest.data[i] = src.data[i];
65  }
66 
67  dest.qMatrix = src.qMatrix;
68  dest.timeSec = src.timeSec;
69  dest.timeMicrosec = src.timeMicrosec;
70  dest.seqNum = src.seqNum;
71  dest.minDisparity = src.minDisparity;
72  dest.maxDisparity = src.maxDisparity;
73  dest.disparityPair = src.disparityPair;
74  dest.referenceCounter = src.referenceCounter;
75 
76  if(dest.referenceCounter != nullptr && countRef) {
77  (*dest.referenceCounter)++;
78  }
79 }
80 
81 void ImagePair::decrementReference() {
82  if(referenceCounter != nullptr && --(*referenceCounter) == 0) {
83  delete []data[0];
84  delete []data[1];
85  delete []qMatrix;
86  delete referenceCounter;
87 
88  data[0] = nullptr;
89  data[1] = nullptr;
90  qMatrix = nullptr;
91  referenceCounter = nullptr;
92  }
93 }
94 
95 void ImagePair::writePgmFile(int imageNumber, const char* fileName) const {
96  if(imageNumber < 0 || imageNumber >1) {
97  throw std::runtime_error("Illegal image number!");
98  }
99 
100  std::fstream strm(fileName, std::ios::out | std::ios::binary);
101 
102  // Write PGM / PBM header
103  int type, maxVal, bytesPerChannel, channels;
104  switch(formats[imageNumber]) {
105  case FORMAT_8_BIT_MONO:
106  type = 5;
107  maxVal = 255;
108  bytesPerChannel = 1;
109  channels = 1;
110  break;
111  case FORMAT_12_BIT_MONO:
112  type = 5;
113  maxVal = 4095;
114  bytesPerChannel = 2;
115  channels = 1;
116  break;
117  case FORMAT_8_BIT_RGB:
118  type = 6;
119  maxVal = 255;
120  bytesPerChannel = 1;
121  channels = 3;
122  break;
123  default:
124  throw std::runtime_error("Illegal pixel format!");
125  }
126 
127  strm << "P" << type << " " << width << " " << height << " " << maxVal << std::endl;
128 
129  // Write image data
130  for(int y = 0; y < height; y++) {
131  for(int x = 0; x < width*channels; x++) {
132  unsigned char* pixel = &data[imageNumber][y*rowStride[imageNumber] + x*bytesPerChannel];
133  if(bytesPerChannel == 2) {
134  // Swap endianess
135  unsigned short swapped = htons(*reinterpret_cast<unsigned short*>(pixel));
136  strm.write(reinterpret_cast<char*>(&swapped), sizeof(swapped));
137  } else {
138  strm.write(reinterpret_cast<char*>(pixel), 1);
139  }
140  }
141  }
142 }
143 
145  dest.decrementReference();
146  copyData(dest, *this, false);
147 
148  dest.qMatrix = new float[16];
149  memcpy(const_cast<float*>(dest.qMatrix), qMatrix, sizeof(float)*16);
150 
151  for(int i=0; i<2; i++) {
152  int bytesPixel = getBytesPerPixel(i);
153 
154  dest.rowStride[i] = width*bytesPixel;
155  dest.data[i] = new unsigned char[height*dest.rowStride[i]];
156 
157  // Convert possibly different row strides
158  for(int y = 0; y < height; y++) {
159  memcpy(&dest.data[i][y*dest.rowStride[i]], &data[i][y*rowStride[i]],
160  dest.rowStride[i]);
161  }
162  }
163 
164  dest.referenceCounter = new int;
165  (*dest.referenceCounter) = 1;
166 }
167 
169  switch(format) {
170  case FORMAT_8_BIT_MONO: return 1;
171  case FORMAT_8_BIT_RGB: return 3;
172  case FORMAT_12_BIT_MONO: return 2;
173  default: throw std::runtime_error("Invalid image format!");
174  }
175 }
void copyTo(ImagePair &dest)
Makes a deep copy of this image pair.
Definition: imagepair.cpp:144
ImagePair()
Default constructor creating an image pair with no pixel data.
Definition: imagepair.cpp:29
ImageFormat
Image formats that can be transferred.
Definition: imagepair.h:38
void writePgmFile(int imageNumber, const char *fileName) const
Writes one image of the pair to a PGM or PPM file.
Definition: imagepair.cpp:95
A set of two images, which are usually the left camera image and the disparity map.
Definition: imagepair.h:33
int getBytesPerPixel(int imageNumber) const
Returns the number of bytes that are required to store one image pixel.
Definition: imagepair.h:279
Nerian Vision Technologies