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