libvisiontransfer  10.6.0
imageset.cpp
1 /*******************************************************************************
2  * Copyright (c) 2023 Allied Vision Technologies 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/imageset.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),
34  referenceCounter(NULL), numberOfImages(2), indexLeftImage(0), indexRightImage(1), indexDisparityImage(-1),
35  indexColorImage(-1), exposureTime(0), lastSyncPulseSec(0), lastSyncPulseMicrosec(0) {
36  for (int i=0; i<MAX_SUPPORTED_IMAGES; ++i) {
37  formats[i] = FORMAT_8_BIT_MONO;
38  data[i] = NULL;
39  rowStride[i] = 0;
40  }
41 }
42 
44  copyData(*this, other, true);
45 }
46 
47 ImageSet& ImageSet::operator= (ImageSet const& other) {
48  if(&other != this) {
49  decrementReference();
50  copyData(*this, other, true);
51  }
52  return *this;
53 }
54 
55 ImageSet::~ImageSet() {
56  decrementReference();
57 }
58 
59 void ImageSet::copyData(ImageSet& dest, const ImageSet& src, bool countRef) {
60  dest.width = src.width;
61  dest.height = src.height;
62 
63  dest.numberOfImages = src.numberOfImages;
64  for(int i=0; i<MAX_SUPPORTED_IMAGES; i++) {
65  dest.rowStride[i] = src.rowStride[i];
66  dest.formats[i] = src.formats[i];
67  dest.data[i] = src.data[i];
68  }
69 
70  dest.qMatrix = src.qMatrix;
71  dest.timeSec = src.timeSec;
72  dest.timeMicrosec = src.timeMicrosec;
73  dest.seqNum = src.seqNum;
74  dest.minDisparity = src.minDisparity;
75  dest.maxDisparity = src.maxDisparity;
76  dest.subpixelFactor = src.subpixelFactor;
77  dest.referenceCounter = src.referenceCounter;
78  dest.numberOfImages = src.numberOfImages;
79  dest.indexLeftImage = src.indexLeftImage;
80  dest.indexRightImage = src.indexRightImage;
81  dest.indexDisparityImage = src.indexDisparityImage;
82  dest.indexColorImage = src.indexColorImage;
83  dest.exposureTime = src.exposureTime;
84  dest.lastSyncPulseSec = src.lastSyncPulseSec;
85  dest.lastSyncPulseMicrosec = src.lastSyncPulseMicrosec;
86 
87  if(dest.referenceCounter != nullptr && countRef) {
88  (*dest.referenceCounter)++;
89  }
90 }
91 
92 void ImageSet::decrementReference() {
93  if(referenceCounter != nullptr && --(*referenceCounter) == 0) {
94  for (int i=0; i<getNumberOfImages(); ++i) {
95  delete []data[i];
96  data[i] = nullptr;
97  }
98  delete []qMatrix;
99  delete referenceCounter;
100 
101  qMatrix = nullptr;
102  referenceCounter = nullptr;
103  }
104 }
105 
106 void ImageSet::writePgmFile(int imageNumber, const char* fileName) const {
107  if(imageNumber < 0 || imageNumber >= getNumberOfImages()) {
108  throw std::runtime_error("Illegal image number!");
109  }
110 
111  std::fstream strm(fileName, std::ios::out | std::ios::binary);
112 
113  // Write PGM / PBM header
114  int type, maxVal, bytesPerChannel, channels;
115  switch(formats[imageNumber]) {
116  case FORMAT_8_BIT_MONO:
117  type = 5;
118  maxVal = 255;
119  bytesPerChannel = 1;
120  channels = 1;
121  break;
122  case FORMAT_12_BIT_MONO:
123  type = 5;
124  maxVal = 4095;
125  bytesPerChannel = 2;
126  channels = 1;
127  break;
128  case FORMAT_8_BIT_RGB:
129  type = 6;
130  maxVal = 255;
131  bytesPerChannel = 1;
132  channels = 3;
133  break;
134  default:
135  throw std::runtime_error("Illegal pixel format!");
136  }
137 
138  strm << "P" << type << " " << width << " " << height << " " << maxVal << std::endl;
139 
140  // Write image data
141  for(int y = 0; y < height; y++) {
142  for(int x = 0; x < width*channels; x++) {
143  unsigned char* pixel = &data[imageNumber][y*rowStride[imageNumber] + x*bytesPerChannel];
144  if(bytesPerChannel == 2) {
145  // Swap endianess
146  unsigned short swapped = htons(*reinterpret_cast<unsigned short*>(pixel));
147  strm.write(reinterpret_cast<char*>(&swapped), sizeof(swapped));
148  } else {
149  strm.write(reinterpret_cast<char*>(pixel), 1);
150  }
151  }
152  }
153 }
154 
155 int ImageSet::getBitsPerPixel(ImageFormat format) {
156  switch(format) {
157  case FORMAT_8_BIT_MONO: return 8;
158  case FORMAT_8_BIT_RGB: return 24;
159  case FORMAT_12_BIT_MONO: return 12;
160  default: throw std::runtime_error("Invalid image format!");
161  }
162 }
163 
165  dest.decrementReference();
166  copyData(dest, *this, false);
167 
168  dest.qMatrix = new float[16];
169  memcpy(const_cast<float*>(dest.qMatrix), qMatrix, sizeof(float)*16);
170 
171  for(int i=0; i<getNumberOfImages(); i++) {
172  int bytesPixel = getBytesPerPixel(i);
173 
174  dest.rowStride[i] = width*bytesPixel;
175  dest.data[i] = new unsigned char[height*dest.rowStride[i]];
176 
177  // Convert possibly different row strides
178  for(int y = 0; y < height; y++) {
179  memcpy(&dest.data[i][y*dest.rowStride[i]], &data[i][y*rowStride[i]],
180  dest.rowStride[i]);
181  }
182  }
183 
184  dest.referenceCounter = new int;
185  (*dest.referenceCounter) = 1;
186 }
187 
189  switch(format) {
190  case FORMAT_8_BIT_MONO: return 1;
191  case FORMAT_8_BIT_RGB: return 3;
192  case FORMAT_12_BIT_MONO: return 2;
193  default: throw std::runtime_error("Invalid image format!");
194  }
195 }
196 
198  assert(imageNumber >= 0 && imageNumber < getNumberOfImages());
199  if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_LEFT)) return ImageSet::ImageType::IMAGE_LEFT;
200  if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_RIGHT)) return ImageSet::ImageType::IMAGE_RIGHT;
201  if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_DISPARITY)) return ImageSet::ImageType::IMAGE_DISPARITY;
202  if (imageNumber == getIndexOf(ImageSet::ImageType::IMAGE_COLOR)) return ImageSet::ImageType::IMAGE_COLOR;
203  throw std::runtime_error("Invalid image number for getImageType!");
204 }
205 
206 void ImageSet::setImageDisparityPair(bool dispPair) {
207  if (getNumberOfImages() != 2) throw std::runtime_error("setImageDisparityPair is only supported for two-image sets");
208  // Let index assignments directly follow the mode
209  indexLeftImage = 0;
210  indexRightImage = dispPair ? -1 : 1;
211  indexDisparityImage = dispPair ? 1 : -1;
212 }
213 
214 int ImageSet::getIndexOf(ImageType what, bool throwIfNotFound) const {
215  int idx = -1;
216  switch(what) {
217  case IMAGE_LEFT: {
218  idx = indexLeftImage;
219  break;
220  }
221  case IMAGE_RIGHT: {
222  idx = indexRightImage;
223  break;
224  }
225  case IMAGE_DISPARITY: {
226  idx = indexDisparityImage;
227  break;
228  }
229  case IMAGE_COLOR: {
230  idx = indexColorImage;
231  break;
232  }
233  default:
234  throw std::runtime_error("Invalid ImageType for query!");
235  }
236  if (throwIfNotFound && (idx==-1)) throw std::runtime_error("ImageSet does not contain the queried ImageType");
237  return idx;
238 }
239 
240 void ImageSet::setIndexOf(ImageType what, int idx) {
241  switch(what) {
242  case IMAGE_LEFT: {
243  indexLeftImage = idx;
244  break;
245  }
246  case IMAGE_RIGHT: {
247  indexRightImage = idx;
248  break;
249  }
250  case IMAGE_DISPARITY: {
251  indexDisparityImage = idx;
252  break;
253  }
254  case IMAGE_COLOR: {
255  indexColorImage = idx;
256  break;
257  }
258  default:
259  throw std::runtime_error("Invalid ImageType for setIndexOf!");
260  }
261 }
262 } // namespace
263 
visiontransfer::ImageSet::setIndexOf
void setIndexOf(ImageType what, int idx)
Assign an image index to a specified ImageType, -1 to disable.
Definition: imageset.cpp:240
visiontransfer::ImageSet::getNumberOfImages
int getNumberOfImages() const
Returns the number of images in this set.
Definition: imageset.h:431
visiontransfer::ImageSet::getIndexOf
int getIndexOf(ImageType what, bool throwIfNotFound=false) const
Returns the index of a specific image type.
Definition: imageset.cpp:214
visiontransfer::ImageSet::copyTo
void copyTo(ImageSet &dest)
Makes a deep copy of this image set.
Definition: imageset.cpp:164
visiontransfer::ImageSet
A set of one to three images, but usually two (the left camera image and the disparity map)....
Definition: imageset.h:50
visiontransfer::ImageSet::FORMAT_8_BIT_RGB
@ FORMAT_8_BIT_RGB
8-bit RGB format
Definition: imageset.h:73
visiontransfer::ImageSet::getBitsPerPixel
int getBitsPerPixel(int imageNumber) const
Returns the number of bits that are required to store one image pixel.
Definition: imageset.h:410
visiontransfer::ImageSet::writePgmFile
void writePgmFile(int imageNumber, const char *fileName) const
Writes one image of the set to a PGM or PPM file.
Definition: imageset.cpp:106
visiontransfer::ImageSet::getBytesPerPixel
int getBytesPerPixel(int imageNumber) const
Returns the number of bytes that are required to store one image pixel.
Definition: imageset.h:399
visiontransfer::ImageSet::ImageType
ImageType
Supported image types.
Definition: imageset.h:91
visiontransfer::ImageSet::ImageFormat
ImageFormat
Image formats that can be transferred.
Definition: imageset.h:68
visiontransfer::ImageSet::ImageSet
ImageSet()
Default constructor creating an image set with no pixel data.
Definition: imageset.cpp:31
visiontransfer::ImageSet::FORMAT_12_BIT_MONO
@ FORMAT_12_BIT_MONO
Definition: imageset.h:77
visiontransfer::ImageSet::FORMAT_8_BIT_MONO
@ FORMAT_8_BIT_MONO
8-bit greyscale format
Definition: imageset.h:70
visiontransfer::ImageSet::IMAGE_COLOR
@ IMAGE_COLOR
3rd color camera for devices where this is supported
Definition: imageset.h:98
visiontransfer::ImageSet::getImageType
ImageType getImageType(int imageNumber) const
Returns the ImageType of the specified channel.
Definition: imageset.cpp:197
Allied Vision