libvisiontransfer  6.5.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 
29 namespace visiontransfer {
30 
32  : width(0), height(0), qMatrix(NULL), timeSec(0), timeMicrosec(0),
33  seqNum(0), minDisparity(0), maxDisparity(0), subpixelFactor(16), disparityPair(false),
34  referenceCounter(NULL) {
35  formats[0] = FORMAT_8_BIT_MONO;
36  formats[1] = FORMAT_8_BIT_MONO;
37  data[0] = NULL;
38  data[1] = NULL;
39  rowStride[0] = 0;
40  rowStride[1] = 1;
41 }
42 
44  copyData(*this, other, true);
45 }
46 
47 ImagePair& ImagePair::operator= (ImagePair const& other) {
48  if(&other != this) {
49  decrementReference();
50  copyData(*this, other, true);
51  }
52  return *this;
53 }
54 
55 ImagePair::~ImagePair() {
56  decrementReference();
57 }
58 
59 void ImagePair::copyData(ImagePair& dest, const ImagePair& src, bool countRef) {
60  dest.width = src.width;
61  dest.height = src.height;
62 
63  for(int i=0; i<2; i++) {
64  dest.rowStride[i] = src.rowStride[i];
65  dest.formats[i] = src.formats[i];
66  dest.data[i] = src.data[i];
67  }
68 
69  dest.qMatrix = src.qMatrix;
70  dest.timeSec = src.timeSec;
71  dest.timeMicrosec = src.timeMicrosec;
72  dest.seqNum = src.seqNum;
73  dest.minDisparity = src.minDisparity;
74  dest.maxDisparity = src.maxDisparity;
75  dest.subpixelFactor = src.subpixelFactor;
76  dest.disparityPair = src.disparityPair;
77  dest.referenceCounter = src.referenceCounter;
78 
79  if(dest.referenceCounter != nullptr && countRef) {
80  (*dest.referenceCounter)++;
81  }
82 }
83 
84 void ImagePair::decrementReference() {
85  if(referenceCounter != nullptr && --(*referenceCounter) == 0) {
86  delete []data[0];
87  delete []data[1];
88  delete []qMatrix;
89  delete referenceCounter;
90 
91  data[0] = nullptr;
92  data[1] = nullptr;
93  qMatrix = nullptr;
94  referenceCounter = nullptr;
95  }
96 }
97 
98 void ImagePair::writePgmFile(int imageNumber, const char* fileName) const {
99  if(imageNumber < 0 || imageNumber >1) {
100  throw std::runtime_error("Illegal image number!");
101  }
102 
103  std::fstream strm(fileName, std::ios::out | std::ios::binary);
104 
105  // Write PGM / PBM header
106  int type, maxVal, bytesPerChannel, channels;
107  switch(formats[imageNumber]) {
108  case FORMAT_8_BIT_MONO:
109  type = 5;
110  maxVal = 255;
111  bytesPerChannel = 1;
112  channels = 1;
113  break;
114  case FORMAT_12_BIT_MONO:
115  type = 5;
116  maxVal = 4095;
117  bytesPerChannel = 2;
118  channels = 1;
119  break;
120  case FORMAT_8_BIT_RGB:
121  type = 6;
122  maxVal = 255;
123  bytesPerChannel = 1;
124  channels = 3;
125  break;
126  default:
127  throw std::runtime_error("Illegal pixel format!");
128  }
129 
130  strm << "P" << type << " " << width << " " << height << " " << maxVal << std::endl;
131 
132  // Write image data
133  for(int y = 0; y < height; y++) {
134  for(int x = 0; x < width*channels; x++) {
135  unsigned char* pixel = &data[imageNumber][y*rowStride[imageNumber] + x*bytesPerChannel];
136  if(bytesPerChannel == 2) {
137  // Swap endianess
138  unsigned short swapped = htons(*reinterpret_cast<unsigned short*>(pixel));
139  strm.write(reinterpret_cast<char*>(&swapped), sizeof(swapped));
140  } else {
141  strm.write(reinterpret_cast<char*>(pixel), 1);
142  }
143  }
144  }
145 }
146 
148  dest.decrementReference();
149  copyData(dest, *this, false);
150 
151  dest.qMatrix = new float[16];
152  memcpy(const_cast<float*>(dest.qMatrix), qMatrix, sizeof(float)*16);
153 
154  for(int i=0; i<2; i++) {
155  int bytesPixel = getBytesPerPixel(i);
156 
157  dest.rowStride[i] = width*bytesPixel;
158  dest.data[i] = new unsigned char[height*dest.rowStride[i]];
159 
160  // Convert possibly different row strides
161  for(int y = 0; y < height; y++) {
162  memcpy(&dest.data[i][y*dest.rowStride[i]], &data[i][y*rowStride[i]],
163  dest.rowStride[i]);
164  }
165  }
166 
167  dest.referenceCounter = new int;
168  (*dest.referenceCounter) = 1;
169 }
170 
172  switch(format) {
173  case FORMAT_8_BIT_MONO: return 1;
174  case FORMAT_8_BIT_RGB: return 3;
175  case FORMAT_12_BIT_MONO: return 2;
176  default: throw std::runtime_error("Invalid image format!");
177  }
178 }
179 
180 } // namespace
181 
void copyTo(ImagePair &dest)
Makes a deep copy of this image pair.
Definition: imagepair.cpp:147
ImagePair()
Default constructor creating an image pair with no pixel data.
Definition: imagepair.cpp:31
void writePgmFile(int imageNumber, const char *fileName) const
Writes one image of the pair to a PGM or PPM file.
Definition: imagepair.cpp:98
ImageFormat
Image formats that can be transferred.
Definition: imagepair.h:38
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:293
Nerian Vision Technologies