SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
CVImage.cpp
Go to the documentation of this file.
1 /**
2  * \file cv/CVImage.cpp
3  * \date Spring 2017
4  * \authors Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #include <CVImage.h>
11 #include <Utils.h>
12 #include <algorithm> // std::max
13 #include <SLFileStorage.h>
14 
15 #ifdef __EMSCRIPTEN__
16 # define STB_IMAGE_IMPLEMENTATION
17 # include "stb_image.h"
18 #endif
19 
20 //-----------------------------------------------------------------------------
21 //! Default constructor
23 {
24  _name = "unknown";
26  _path = "";
27  _bytesPerPixel = 0;
28  _bytesPerLine = 0;
29  _bytesPerImage = 0;
30  _bytesInFile = 0;
31 };
32 //------------------------------------------------------------------------------
33 //! Constructor for empty image of a certain format and size
34 CVImage::CVImage(int width,
35  int height,
36  CVPixelFormatGL pixelFormatGL,
37  string name) : _name(std::move(name))
38 {
39  allocate(width, height, pixelFormatGL);
40 }
41 //-----------------------------------------------------------------------------
42 //! Constructor for image from file
43 CVImage::CVImage(const string& filename,
44  bool flipVertical,
45  bool loadGrayscaleIntoAlpha)
46  : _name(Utils::getFileName(filename))
47 {
48  assert(filename != "");
49  clearData();
50  load(filename, flipVertical, loadGrayscaleIntoAlpha);
51 }
52 //-----------------------------------------------------------------------------
53 //! Copy constructor from a source image
54 CVImage::CVImage(CVImage& src) : _name(src.name())
55 {
56  assert(src.width() && src.height() && src.data());
57  _format = src.format();
58  _path = src.path();
62  _bytesInFile = src.bytesInFile();
63  src.cvMat().copyTo(_cvMat);
64 }
65 //-----------------------------------------------------------------------------
66 //! Creates a 1D image from a CVVec3f color vector
67 CVImage::CVImage(const CVVVec3f& colors)
68 {
69  allocate((int)colors.size(), 1, PF_rgb);
70 
71  int x = 0;
72  for (auto color : colors)
73  {
74  _cvMat.at<CVVec3b>(0, x++) = CVVec3b((uchar)(color[0] * 255.0f),
75  (uchar)(color[1] * 255.0f),
76  (uchar)(color[2] * 255.0f));
77  }
78 }
79 //-----------------------------------------------------------------------------
80 //! Creates a 1D image from a CVVec4f vector
81 CVImage::CVImage(const CVVVec4f& colors)
82 {
83  allocate((int)colors.size(), 1, PF_rgba);
84 
85  int x = 0;
86  for (auto color : colors)
87  {
88  _cvMat.at<CVVec4b>(0, x++) = CVVec4b((uchar)(color[0] * 255.0f),
89  (uchar)(color[1] * 255.0f),
90  (uchar)(color[2] * 255.0f),
91  (uchar)(color[3] * 255.0f));
92  }
93 }
94 //-----------------------------------------------------------------------------
96 {
97  // Utils::log("CVImages)", name().c_str());
98  clearData();
99 }
100 //-----------------------------------------------------------------------------
101 //! Deletes all data and resets the image parameters
103 {
104  _cvMat.release();
105  _bytesPerPixel = 0;
106  _bytesPerLine = 0;
107  _bytesPerImage = 0;
108  _bytesInFile = 0;
109  _path = "";
110 }
111 //-----------------------------------------------------------------------------
112 //! Memory allocation function
113 /*! It returns true if width or height or the pixelformat has changed
114 /param width Width of image in pixels
115 /param height Height of image in pixels
116 /param pixelFormatGL OpenGL pixel format enum
117 /param isContinuous True if the memory is continuous and has no stride bytes at the end of the line
118 */
119 bool CVImage::allocate(int width,
120  int height,
121  CVPixelFormatGL pixelFormatGL,
122  bool isContinuous)
123 {
124  assert(width > 0 && height > 0);
125 
126  // return if essentials are identical
127  if (!_cvMat.empty() &&
128  _cvMat.cols == width &&
129  _cvMat.rows == height &&
130  _format == pixelFormatGL)
131  return false;
132 
133  // Set the according OpenCV format
134  int cvType = glPixelFormat2cvType(pixelFormatGL);
135  _cvMat.create(height, width, cvType);
136 
137  _format = pixelFormatGL;
138  _bytesPerPixel = bytesPerPixel(pixelFormatGL);
140  pixelFormatGL,
141  isContinuous);
143 
144  if (!_cvMat.data)
145  Utils::exitMsg("SLProject",
146  "CVImage::Allocate: Allocation failed",
147  __LINE__,
148  __FILE__);
149  return true;
150 }
151 //-----------------------------------------------------------------------------
152 //! Returns the NO. of bytes per pixel for the passed pixel format
154 {
155  switch (pixFormatGL)
156  {
157  case PF_red:
158  case PF_red_integer:
159  case PF_green:
160  case PF_alpha:
161  case PF_blue:
162  case PF_luminance:
163  case PF_intensity: return 1;
164  case PF_rg:
165  case PF_rg_integer:
166  case PF_luminance_alpha: return 2;
167  case PF_rgb:
168  case PF_bgr:
169  case PF_rgb_integer:
170  case PF_bgr_integer: return 3;
171  case PF_rgba:
172  case PF_bgra:
173  case PF_rgba_integer:
174  case PF_bgra_integer: return 4;
175  case PF_r16f: return 2;
176  case PF_rg16f: return 4;
177  case PF_rgb16f: return 6;
178  case PF_rgba16f: return 8;
179  case PF_r32f: return 4;
180  case PF_rg32f: return 8;
181  case PF_rgb32f: return 12;
182  case PF_rgba32f: return 16;
183  default:
184  Utils::exitMsg("SLProject", "CVImage::bytesPerPixel: unknown pixel format", __LINE__, __FILE__);
185  }
186  return 0;
187 }
188 //-----------------------------------------------------------------------------
189 //! Returns the NO. of bytes per image line for the passed pixel format
190 /*
191 /param width Width of image in pixels
192 /param pixelFormatGL OpenGL pixel format enum
193 /param isContinuous True if the memory is continuous and has no stride bytes at the end of the line
194 */
195 uint CVImage::bytesPerLine(uint width,
196  CVPixelFormatGL format,
197  bool isContinuous)
198 {
199  uint bpp = bytesPerPixel(format);
200  uint bitsPerPixel = bpp * 8;
201  uint bpl = isContinuous ? width * bpp : ((width * bitsPerPixel + 31) / 32) * 4;
202  return bpl;
203 }
204 //-----------------------------------------------------------------------------
205 //! loads an image from a memory with format change.
206 /*! It returns true if the width, height or destination format has changed so
207 that the depending texture can be rebuild in OpenGL. If the source and
208 destination pixel format does not match a conversion for certain formats is
209 done.
210 /param width Width of image in pixels
211 /param height Height of image in pixels
212 /param srcPixelFormatGL OpenGL pixel format enum of source image
213 /param dstPixelFormatGL OpenGL pixel format enum of destination image
214 /param data Pointer to the first byte of the image data
215 /param isContinuous True if the memory is continuous and has no stride bytes at the end of the line
216 /param isTopLeft True if image data starts at top left of image (else bottom left)
217 */
218 bool CVImage::load(int width,
219  int height,
220  CVPixelFormatGL srcPixelFormatGL,
221  CVPixelFormatGL dstPixelFormatGL,
222  uchar* data,
223  bool isContinuous,
224  bool isTopLeft)
225 {
226 
227  bool needsTextureRebuild = allocate(width,
228  height,
229  dstPixelFormatGL,
230  false);
231  uint dstBPL = _bytesPerLine;
232  uint dstBPP = _bytesPerPixel;
233  uint srcBPP = bytesPerPixel(srcPixelFormatGL);
234  uint srcBPL = bytesPerLine((uint)width, srcPixelFormatGL, isContinuous);
235 
236  if (isTopLeft)
237  {
238  // copy lines and flip vertically
239  uchar* dstStart = _cvMat.data + _bytesPerImage - dstBPL;
240  uchar* srcStart = data;
241 
242  if (srcPixelFormatGL == dstPixelFormatGL)
243  {
244  for (int h = 0; h < _cvMat.rows; ++h, srcStart += srcBPL, dstStart -= dstBPL)
245  {
246  memcpy(dstStart, srcStart, (unsigned long)dstBPL);
247  }
248  }
249  else
250  {
251  if (srcPixelFormatGL == PF_bgra)
252  {
253  if (dstPixelFormatGL == PF_rgb)
254  {
255  for (int h = 0; h < _cvMat.rows; ++h, srcStart += srcBPL, dstStart -= dstBPL)
256  {
257  uchar* src = srcStart;
258  uchar* dst = dstStart;
259  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
260  {
261  dst[0] = src[2];
262  dst[1] = src[1];
263  dst[2] = src[0];
264  }
265  }
266  }
267  else if (dstPixelFormatGL == PF_rgba)
268  {
269  for (int h = 0; h < _cvMat.rows; ++h, srcStart += srcBPL, dstStart -= dstBPL)
270  {
271  uchar* src = srcStart;
272  uchar* dst = dstStart;
273  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
274  {
275  dst[0] = src[2];
276  dst[1] = src[1];
277  dst[2] = src[0];
278  dst[3] = src[3];
279  }
280  }
281  }
282  }
283  else if (srcPixelFormatGL == PF_bgr || srcPixelFormatGL == PF_rgb)
284  {
285  if (dstPixelFormatGL == PF_rgb || dstPixelFormatGL == PF_bgr)
286  {
287  for (int h = 0; h < _cvMat.rows; ++h, srcStart += srcBPL, dstStart -= dstBPL)
288  {
289  uchar* src = srcStart;
290  uchar* dst = dstStart;
291  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
292  {
293  dst[0] = src[2];
294  dst[1] = src[1];
295  dst[2] = src[0];
296  }
297  }
298  }
299  }
300  else
301  {
302  std::cout << "CVImage::load from memory: Pixel format conversion not allowed" << std::endl;
303  exit(1);
304  }
305  }
306  }
307  else // bottom left (no flipping)
308  {
309  if (srcPixelFormatGL == dstPixelFormatGL)
310  {
311  memcpy(_cvMat.data, data, (unsigned long)_bytesPerImage);
312  }
313  else
314  {
315  uchar* dstStart = _cvMat.data;
316  uchar* srcStart = data;
317 
318  if (srcPixelFormatGL == PF_bgra)
319  {
320  if (dstPixelFormatGL == PF_rgb)
321  {
322  for (int h = 0; h < _cvMat.rows - 1; ++h, srcStart += srcBPL, dstStart += dstBPL)
323  {
324  uchar* src = srcStart;
325  uchar* dst = dstStart;
326  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
327  {
328  dst[0] = src[2];
329  dst[1] = src[1];
330  dst[2] = src[0];
331  }
332  }
333  }
334  else if (dstPixelFormatGL == PF_rgba)
335  {
336  for (int h = 0; h < _cvMat.rows - 1; ++h, srcStart += srcBPL, dstStart += dstBPL)
337  {
338  uchar* src = srcStart;
339  uchar* dst = dstStart;
340  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
341  {
342  dst[0] = src[2];
343  dst[1] = src[1];
344  dst[2] = src[0];
345  dst[3] = src[3];
346  }
347  }
348  }
349  }
350  else if (srcPixelFormatGL == PF_bgr || srcPixelFormatGL == PF_rgb)
351  {
352  if (dstPixelFormatGL == PF_rgb || dstPixelFormatGL == PF_bgr)
353  {
354  for (int h = 0; h < _cvMat.rows - 1; ++h, srcStart += srcBPL, dstStart += dstBPL)
355  {
356  uchar* src = srcStart;
357  uchar* dst = dstStart;
358  for (int w = 0; w < _cvMat.cols - 1; ++w, dst += dstBPP, src += srcBPP)
359  {
360  dst[0] = src[2];
361  dst[1] = src[1];
362  dst[2] = src[0];
363  }
364  }
365  }
366  }
367  else
368  {
369  std::cout << "CVImage::load from memory: Pixel format conversion not allowed" << std::endl;
370  exit(1);
371  }
372  }
373  }
374 
375  return needsTextureRebuild;
376 }
377 //-----------------------------------------------------------------------------
378 //! Loads the image with the appropriate image loader
379 void CVImage::load(const string& filename,
380  bool flipVertical,
381  bool loadGrayscaleIntoAlpha)
382 {
383  string ext = Utils::getFileExt(filename);
384  _name = Utils::getFileName(filename);
385  _path = Utils::getPath(filename);
386  _bytesInFile = Utils::getFileSize(filename);
387 
388  // Load the image from the file.
389  // On most platforms, we use OpenCV for image loading, but on Emscripten there is no
390  // `cv::imread` function, so we use stb_image instead.
391 
392 #ifndef __EMSCRIPTEN__
393  _cvMat = cv::imread(filename, cv::ImreadModes::IMREAD_UNCHANGED);
394 #else
396 
397  unsigned char* encodedData = buffer.data;
398  int size = (int)buffer.size;
399  int width;
400  int height;
401  int numChannels;
402  stbi_hdr_to_ldr_gamma(1.0f);
403  unsigned char* data = stbi_load_from_memory(encodedData, size, &width, &height, &numChannels, 0);
404  _cvMat = CVMat(height, width, CV_8UC(numChannels), data);
405 
406  buffer.deallocate();
407 #endif
408 
409  if (!_cvMat.data)
410  {
411  string msg = "CVImage.load: Loading failed: " + filename;
412  Utils::exitMsg("SLProject", msg.c_str(), __LINE__, __FILE__);
413  }
414 
415  // Convert greater component depth than 8 bit to 8 bit, only if the image is not HDR
416  if (_cvMat.depth() > CV_8U && ext != "hdr")
417  _cvMat.convertTo(_cvMat, CV_8U, 1.0 / 256.0);
418 
419 #ifndef __EMSCRIPTEN__
421 #else
422  // When using stb_image instead of OpenCV to load the file, the format is always RGB(A)
423  // and not BGR(A). We have to handle these two cases differently because
424  // `cvType2glPixelFormat` assumes for example that CV_8UC3 corresponds to PF_bgr and not PF_rgb.
425 
426  if (_cvMat.type() == CV_8UC3)
427  _format = PF_rgb;
428  else if (_cvMat.type() == CV_8UC4)
429  _format = PF_rgba;
430  else
432 #endif
433 
435 
436  // OpenCV always loads with BGR(A) but OpenGL uses RGB(A)
437  if (_format == PF_bgr || _format == PF_rgb32f)
438  {
439  string typeStr1 = typeString(_cvMat.type());
440  cv::cvtColor(_cvMat, _cvMat, cv::COLOR_BGR2RGB);
441  string typeStr2 = typeString(_cvMat.type());
442  _format = PF_rgb;
443  }
444  else if (_format == PF_bgra)
445  {
446  cv::cvtColor(_cvMat, _cvMat, cv::COLOR_BGRA2RGBA);
447  _format = PF_rgba;
448  }
449  else if (_format == PF_red && loadGrayscaleIntoAlpha)
450  {
451  CVMat rgbaImg;
452  rgbaImg.create(_cvMat.rows, _cvMat.cols, CV_8UC4);
453 
454  // Copy grayscale into alpha channel
455  for (int y = 0; y < rgbaImg.rows; ++y)
456  {
457  uchar* dst = rgbaImg.ptr<uchar>(y);
458  uchar* src = _cvMat.ptr<uchar>(y);
459 
460  for (int x = 0; x < rgbaImg.cols; ++x)
461  {
462  *dst++ = 0; // B
463  *dst++ = 0; // G
464  *dst++ = 0; // R
465  *dst++ = *src++; // A
466  }
467  }
468 
469  _cvMat = rgbaImg;
470  cv::cvtColor(_cvMat, _cvMat, cv::COLOR_BGRA2RGBA);
471  _format = PF_rgba;
472 
473  // for debug check
474  // string pathfilename = _path + name();
475  // string filename = Utils::getFileNameWOExt(pathfilename);
476  // savePNG(_path + filename + "_InAlpha.png");
477  }
478 
479  switch (_cvMat.type())
480  {
481  case CV_8UC1: _format = PF_red; break;
482  case CV_8UC2: _format = PF_rg; break;
483  case CV_8UC3: _format = PF_rgb; break;
484  case CV_8UC4: _format = PF_rgba; break;
485  }
486 
488 
489  if (_format == PF_red && loadGrayscaleIntoAlpha)
490  {
491  CVMat rgbaImg;
492  rgbaImg.create(_cvMat.rows, _cvMat.cols, CV_8UC4);
493 
494  // Copy grayscale into alpha channel
495  for (int y = 0; y < rgbaImg.rows; ++y)
496  {
497  uchar* dst = rgbaImg.ptr<uchar>(y);
498  uchar* src = _cvMat.ptr<uchar>(y);
499 
500  for (int x = 0; x < rgbaImg.cols; ++x)
501  {
502  uchar value = *src++;
503  *dst++ = value;
504  *dst++ = value;
505  *dst++ = value;
506  *dst++ = value;
507  }
508  }
509 
510  _format = PF_rgba;
511  }
512 
513  _bytesPerLine = bytesPerLine((uint)_cvMat.cols, _format, _cvMat.isContinuous());
514  _bytesPerImage = _bytesPerLine * (uint)_cvMat.rows;
515 
516  // OpenCV loads top-left but OpenGL is bottom left
517  if (flipVertical)
518  flipY();
519 }
520 //-----------------------------------------------------------------------------
521 //! Converts OpenCV mat type to OpenGL pixel format
523 {
524  switch (cvType)
525  {
526  case CV_8UC1: return PF_red;
527  case CV_8UC2: return PF_rg;
528  case CV_8UC3: return PF_bgr;
529  case CV_8UC4: return PF_bgra;
530  case CV_16FC1: return PF_r16f;
531  case CV_16FC2: return PF_rg16f;
532  case CV_16FC3: return PF_rgb16f;
533  case CV_16FC4: return PF_rgba16f;
534  case CV_32FC1: return PF_r32f;
535  case CV_32FC2: return PF_rg32f;
536  case CV_32FC3: return PF_rgb32f;
537  case CV_32FC4: return PF_rgba32f;
538  case CV_8SC1: Utils::exitMsg("SLProject", "OpenCV image format CV_8SC1 not supported", __LINE__, __FILE__); break;
539  case CV_8SC2: Utils::exitMsg("SLProject", "OpenCV image format CV_8SC2 not supported", __LINE__, __FILE__); break;
540  case CV_8SC3: Utils::exitMsg("SLProject", "OpenCV image format CV_8SC3 not supported", __LINE__, __FILE__); break;
541  case CV_8SC4: Utils::exitMsg("SLProject", "OpenCV image format CV_8SC4 not supported", __LINE__, __FILE__); break;
542  case CV_16UC1: Utils::exitMsg("SLProject", "OpenCV image format CV_16UC1 not supported", __LINE__, __FILE__); break;
543  case CV_16UC2: Utils::exitMsg("SLProject", "OpenCV image format CV_16UC2 not supported", __LINE__, __FILE__); break;
544  case CV_16UC3: Utils::exitMsg("SLProject", "OpenCV image format CV_16UC3 not supported", __LINE__, __FILE__); break;
545  case CV_16UC4: Utils::exitMsg("SLProject", "OpenCV image format CV_16UC4 not supported", __LINE__, __FILE__); break;
546  case CV_16SC1: Utils::exitMsg("SLProject", "OpenCV image format CV_16SC1 not supported", __LINE__, __FILE__); break;
547  case CV_16SC2: Utils::exitMsg("SLProject", "OpenCV image format CV_16SC2 not supported", __LINE__, __FILE__); break;
548  case CV_16SC3: Utils::exitMsg("SLProject", "OpenCV image format CV_16SC3 not supported", __LINE__, __FILE__); break;
549  case CV_16SC4: Utils::exitMsg("SLProject", "OpenCV image format CV_16SC4 not supported", __LINE__, __FILE__); break;
550  case CV_32SC1: Utils::exitMsg("SLProject", "OpenCV image format CV_32SC1 not supported", __LINE__, __FILE__); break;
551  case CV_32SC2: Utils::exitMsg("SLProject", "OpenCV image format CV_32SC2 not supported", __LINE__, __FILE__); break;
552  case CV_32SC3: Utils::exitMsg("SLProject", "OpenCV image format CV_32SC3 not supported", __LINE__, __FILE__); break;
553  case CV_32SC4: Utils::exitMsg("SLProject", "OpenCV image format CV_32SC4 not supported", __LINE__, __FILE__); break;
554  default: Utils::exitMsg("SLProject",
555  "glPixelFormat2cvType: OpenCV image format not supported",
556  __LINE__,
557  __FILE__);
558  }
559  return PF_unknown;
560 }
561 //-----------------------------------------------------------------------------
562 //! Converts OpenGL pixel format to OpenCV mat type
564 {
565  switch (pixelFormatGL)
566  {
567  case PF_red:
568  case PF_luminance: return CV_8UC1;
569  case PF_luminance_alpha:
570  case PF_rg: return CV_8UC2;
571  case PF_rgb: return CV_8UC3;
572  case PF_rgba: return CV_8UC4;
573  case PF_bgr: return CV_8UC3;
574  case PF_bgra: return CV_8UC4;
575  case PF_r16f: return CV_16FC1;
576  case PF_rg16f: return CV_16FC2;
577  case PF_rgb16f: return CV_16FC3;
578  case PF_rgba16f: return CV_16FC4;
579  case PF_r32f: return CV_32FC1;
580  case PF_rg32f: return CV_32FC2;
581  case PF_rgb32f: return CV_32FC3;
582  case PF_rgba32f: return CV_32FC4;
583  default:
584  {
585  string msg = "glPixelFormat2cvType: OpenGL pixel format not supported: ";
586  msg += formatString(pixelFormatGL);
587  Utils::exitMsg("SLProject", msg.c_str(), __LINE__, __FILE__);
588  }
589  }
590  return -1;
591 }
592 //-----------------------------------------------------------------------------
593 //! Returns the pixel format as string
595 {
596  switch (pixelFormatGL)
597  {
598  case PF_unknown: return "PF_unknown";
599  case PF_yuv_420_888: return "PF_yuv_420_888";
600  case PF_alpha: return "PF_alpha";
601  case PF_luminance: return "PF_luminance";
602  case PF_luminance_alpha: return "PF_luminance_alpha";
603  case PF_intensity: return "PF_intensity";
604  case PF_green: return "PF_green";
605  case PF_blue: return "PF_blue";
606  case PF_depth_component: return "PF_depth_component";
607  case PF_red: return "PF_red";
608  case PF_rg: return "PF_rg";
609  case PF_rgb: return "PF_rgb";
610  case PF_rgba: return "PF_rgba";
611  case PF_bgr: return "PF_bgr";
612  case PF_bgra: return "PF_bgra";
613  case PF_rg_integer: return "PF_rg_integer";
614  case PF_red_integer: return "PF_red_integer";
615  case PF_rgb_integer: return "PF_rgb_integer";
616  case PF_rgba_integer: return "PF_rgba_integer";
617  case PF_bgr_integer: return "PF_bgr_integer";
618  case PF_bgra_integer: return "PF_bgra_integer";
619  case PF_r16f: return "PF_r16f";
620  case PF_r32f: return "PF_r32f";
621  case PF_rg16f: return "PF_rg16f";
622  case PF_rg32f: return "PF_rg32f";
623  case PF_rgba32f: return "PF_rgba32f";
624  case PF_rgba16f: return "PF_rgba16f";
625  case PF_rgb16f: return "PF_rgb16f";
626  default: return string("Unknown pixel format");
627  }
628 }
629 //-----------------------------------------------------------------------------
630 //! Save as PNG at a certain compression level (0-9)
631 /*!Save as PNG at a certain compression level (0-9)
632 @param filename filename with path and extension
633 @param compressionLevel compression level 0-9 (default 6)
634 @param flipY Flag for vertical mirroring
635 @param convertBGR2RGB Flag for BGR to RGB conversion
636 */
637 void CVImage::savePNG(const string& filename,
638  const int compressionLevel,
639  const bool flipY,
640  const bool convertToRGB)
641 {
642 #ifndef __EMSCRIPTEN__
643  vector<int> compression_params;
644  compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
645  compression_params.push_back(compressionLevel);
646 
647  try
648  {
649  CVMat outImg = _cvMat.clone();
650 
651  if (flipY)
652  cv::flip(outImg, outImg, 0);
653  if (convertToRGB)
654  cv::cvtColor(outImg, outImg, cv::COLOR_BGR2RGB);
655 
656  imwrite(filename, outImg, compression_params);
657  }
658  catch (std::runtime_error& ex)
659  {
660  string msg = "CVImage.savePNG: Exception: ";
661  msg += ex.what();
662  Utils::exitMsg("SLProject", msg.c_str(), __LINE__, __FILE__);
663  }
664 #endif
665 }
666 
667 //-----------------------------------------------------------------------------
668 //! Save as JPG at a certain compression level (0-100)
669 /*!Save as JPG at a certain compression level (0-100)
670 @param filename filename with path and extension
671 @param compressionLevel compression level 0-100 (default 95)
672 @param flipY Flag for vertical mirroring
673 @param convertBGR2RGB Flag for BGR to RGB conversion
674 */
675 void CVImage::saveJPG(const string& filename,
676  const int compressionLevel,
677  const bool flipY,
678  const bool convertBGR2RGB)
679 {
680 #ifndef __EMSCRIPTEN__
681  vector<int> compression_params;
682  compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
683  compression_params.push_back(cv::IMWRITE_JPEG_PROGRESSIVE);
684  compression_params.push_back(compressionLevel);
685 
686  try
687  {
688  CVMat outImg = _cvMat.clone();
689 
690  if (flipY)
691  cv::flip(outImg, outImg, 0);
692  if (convertBGR2RGB)
693  cv::cvtColor(outImg, outImg, cv::COLOR_BGR2RGB);
694 
695  imwrite(filename, outImg, compression_params);
696  }
697  catch (std::runtime_error& ex)
698  {
699  string msg = "CVImage.saveJPG: Exception: ";
700  msg += ex.what();
701  Utils::exitMsg("SLProject", msg.c_str(), __LINE__, __FILE__);
702  }
703 #endif
704 }
705 //-----------------------------------------------------------------------------
706 //! getPixeli returns the pixel color at the integer pixel coordinate x, y
707 /*! Returns the pixel color at the integer pixel coordinate x, y. The color
708 components range from 0-1 float.
709 */
711 {
712  CVVec4f color;
713 
714  x %= _cvMat.cols;
715  y %= _cvMat.rows;
716 
717  switch (_format)
718  {
719  case PF_rgb:
720  {
721  CVVec3b c = _cvMat.at<CVVec3b>(y, x);
722  color[0] = c[0];
723  color[1] = c[1];
724  color[2] = c[2];
725  color[3] = 255.0f;
726  break;
727  }
728  case PF_rgba:
729  {
730  color = _cvMat.at<CVVec4b>(y, x);
731  break;
732  }
733  case PF_bgr:
734  {
735  CVVec3b c = _cvMat.at<CVVec3b>(y, x);
736  color[0] = c[2];
737  color[1] = c[1];
738  color[2] = c[0];
739  color[3] = 255.0f;
740  break;
741  }
742  case PF_bgra:
743  {
744  CVVec4b c = _cvMat.at<CVVec4b>(y, x);
745  color[0] = c[2];
746  color[1] = c[1];
747  color[2] = c[0];
748  color[3] = c[3];
749  break;
750  }
751 #ifdef APP_USES_GLES
752  case PF_luminance:
753 #else
754  case PF_red:
755 #endif
756  {
757  uchar c = _cvMat.at<uchar>(y, x);
758  color[0] = (float)c;
759  color[1] = (float)c;
760  color[2] = (float)c;
761  color[3] = 255.0f;
762  break;
763  }
764 #ifdef APP_USES_GLES
765  case PF_luminance_alpha:
766 #else
767  case PF_rg:
768 #endif
769  {
770  CVVec2b c = _cvMat.at<cv::Vec2b>(y, x);
771  color[0] = c[0];
772  color[1] = c[0];
773  color[2] = c[0];
774  color[3] = c[1];
775  break;
776  }
777  default: Utils::exitMsg("SLProject", "CVImage::getPixeli: Unknown format!", __LINE__, __FILE__);
778  }
779  color /= 255.0f;
780  return color;
781 }
782 //-----------------------------------------------------------------------------
783 /*!
784 getPixelf returns a pixel color with its x & y texture coordinates.
785 If the OpenGL filtering is set to GL_LINEAR a bilinear interpolated color out
786 of four neighbouring pixels is return. Otherwise the nearest pixel is returned.
787 */
788 CVVec4f CVImage::getPixelf(float x, float y)
789 {
790  // Bilinear interpolation
791  float xf = Utils::fract(x) * _cvMat.cols;
792  float yf = Utils::fract(y) * _cvMat.rows;
793 
794  // corrected fractional parts
795  float fracX = Utils::fract(xf);
796  float fracY = Utils::fract(yf);
797  fracX -= Utils::sign(fracX - 0.5f) * 0.5f;
798  fracY -= Utils::sign(fracY - 0.5f) * 0.5f;
799 
800  // calculate area weights of the four neighbouring texels
801  float X1 = 1.0f - fracX;
802  float Y1 = 1.0f - fracY;
803  float UL = X1 * Y1;
804  float UR = fracX * Y1;
805  float LL = X1 * fracY;
806  float LR = fracX * fracY;
807 
808  // get the color of the four neighbouring texels
809  // int xm, xp, ym, yp;
810  // Fast2Int(&xm, xf-1.0f);
811  // Fast2Int(&ym, yf-1.0f);
812  // Fast2Int(&xp, xf);
813  // Fast2Int(&yp, yf);
814  //
815  // SLCol4f cUL = getPixeli(xm,ym);
816  // SLCol4f cUR = getPixeli(xp,ym);
817  // SLCol4f cLL = getPixeli(xm,yp);
818  // SLCol4f cLR = getPixeli(xp,yp);
819 
820  CVVec4f cUL = getPixeli((int)(xf - 0.5f), (int)(yf - 0.5f));
821  CVVec4f cUR = getPixeli((int)(xf + 0.5f), (int)(yf - 0.5f));
822  CVVec4f cLL = getPixeli((int)(xf - 0.5f), (int)(yf + 0.5f));
823  CVVec4f cLR = getPixeli((int)(xf + 0.5f), (int)(yf + 0.5f));
824 
825  // calculate a new interpolated color with the area weights
826  float r = UL * cUL[0] + LL * cLL[0] + UR * cUR[0] + LR * cLR[0];
827  float g = UL * cUL[1] + LL * cLL[1] + UR * cUR[1] + LR * cLR[1];
828  float b = UL * cUL[2] + LL * cLL[2] + UR * cUR[2] + LR * cLR[2];
829 
830  return CVVec4f(r, g, b, 1.0f);
831 }
832 //-----------------------------------------------------------------------------
833 //! setPixeli sets the RGB pixel color at the integer pixel coordinate x, y
834 void CVImage::setPixeli(int x, int y, CVVec4f color)
835 {
836  if (x < 0) x = 0;
837  if (x >= (int)_cvMat.cols) x = _cvMat.cols - 1; // 0 <= x < _width
838  if (y < 0) y = 0;
839  if (y >= (int)_cvMat.rows) y = _cvMat.rows - 1; // 0 <= y < _height
840 
841  int R, G, B;
842 
843  switch (_format)
844  {
845  case PF_rgb:
846  _cvMat.at<CVVec3b>(y, x) = CVVec3b((uchar)(color[0] * 255.0f),
847  (uchar)(color[1] * 255.0f),
848  (uchar)(color[2] * 255.0f));
849  break;
850  case PF_bgr:
851  _cvMat.at<CVVec3b>(y, x) = CVVec3b((uchar)(color[2] * 255.0f),
852  (uchar)(color[1] * 255.0f),
853  (uchar)(color[0] * 255.0f));
854  break;
855  case PF_rgba:
856  _cvMat.at<CVVec4b>(y, x) = CVVec4b((uchar)(color[0] * 255.0f),
857  (uchar)(color[1] * 255.0f),
858  (uchar)(color[2] * 255.0f),
859  (uchar)(color[3] * 255.0f));
860  break;
861  case PF_bgra:
862  _cvMat.at<CVVec4b>(y, x) = CVVec4b((uchar)(color[2] * 255.0f),
863  (uchar)(color[1] * 255.0f),
864  (uchar)(color[0] * 255.0f),
865  (uchar)(color[3] * 255.0f));
866  break;
867 #ifdef APP_USES_GLES
868  case PF_luminance:
869 #else
870  case PF_red:
871 #endif
872  R = (int)(color[0] * 255.0f);
873  G = (int)(color[1] * 255.0f);
874  B = (int)(color[2] * 255.0f);
875  _cvMat.at<uchar>(y, x) = (uchar)(((66 * R + 129 * G + 25 * B + 128) >> 8) + 16);
876  break;
877 #ifdef APP_USES_GLES
878  case PF_luminance_alpha:
879 #else
880  case PF_rg:
881 #endif
882  R = (int)(color[0] * 255.0f);
883  G = (int)(color[1] * 255.0f);
884  B = (int)(color[2] * 255.0f);
885  _cvMat.at<CVVec2b>(y, x) = CVVec2b((uchar)(((66 * R + 129 * G + 25 * B + 128) >> 8) + 16),
886  (uchar)(color[3] * 255.0f));
887  break;
888  default: Utils::exitMsg("SLProject", "CVImage::setPixeli: Unknown format!", __LINE__, __FILE__);
889  }
890 }
891 //-----------------------------------------------------------------------------
892 //! setPixeli sets the RGB pixel color at the integer pixel coordinate x, y
893 void CVImage::setPixeliRGB(int x, int y, CVVec3f color)
894 {
895  assert(_bytesPerPixel == 3);
896  if (x < 0) x = 0;
897  if (x >= (int)_cvMat.cols) x = _cvMat.cols - 1; // 0 <= x < _width
898  if (y < 0) y = 0;
899  if (y >= (int)_cvMat.rows) y = _cvMat.rows - 1; // 0 <= y < _height
900 
901  _cvMat.at<CVVec3b>(y, x) = CVVec3b((uchar)(color[0] * 255.0f + 0.5f),
902  (uchar)(color[1] * 255.0f + 0.5f),
903  (uchar)(color[2] * 255.0f + 0.5f));
904 }
905 //-----------------------------------------------------------------------------
906 //! setPixeli sets the RGB pixel color at the integer pixel coordinate x, y
907 void CVImage::setPixeliRGB(int x, int y, CVVec4f color)
908 {
909  assert(_bytesPerPixel == 3);
910  if (x < 0) x = 0;
911  if (x >= (int)_cvMat.cols) x = _cvMat.cols - 1; // 0 <= x < _width
912  if (y < 0) y = 0;
913  if (y >= (int)_cvMat.rows) y = _cvMat.rows - 1; // 0 <= y < _height
914 
915  _cvMat.at<CVVec3b>(y, x) = CVVec3b((uchar)(color[0] * 255.0f + 0.5f),
916  (uchar)(color[1] * 255.0f + 0.5f),
917  (uchar)(color[2] * 255.0f + 0.5f));
918 }
919 //-----------------------------------------------------------------------------
920 //! setPixeli sets the RGBA pixel color at the integer pixel coordinate x, y
921 void CVImage::setPixeliRGBA(int x, int y, CVVec4f color)
922 {
923  assert(_bytesPerPixel == 4);
924  if (x < 0) x = 0;
925  if (x >= (int)_cvMat.cols) x = _cvMat.cols - 1; // 0 <= x < _width
926  if (y < 0) y = 0;
927  if (y >= (int)_cvMat.rows) y = _cvMat.rows - 1; // 0 <= y < _height
928 
929  _cvMat.at<CVVec4b>(y, x) = CVVec4b((uchar)(color[0] * 255.0f + 0.5f),
930  (uchar)(color[1] * 255.0f + 0.5f),
931  (uchar)(color[2] * 255.0f + 0.5f),
932  (uchar)(color[3] * 255.0f + 0.5f));
933 }
934 //-----------------------------------------------------------------------------
935 /*!
936 CVImage::Resize does a scaling with bilinear interpolation.
937 */
938 void CVImage::resize(int width, int height)
939 {
940  assert(_cvMat.cols > 0 && _cvMat.rows > 0 && width > 0 && height > 0);
941  if (_cvMat.cols == width && _cvMat.rows == height) return;
942 
943  CVMat dst = CVMat(height, width, _cvMat.type());
944 
945  cv::resize(_cvMat, dst, dst.size(), 0, 0, cv::INTER_LINEAR);
946 
947  _cvMat = dst;
948 }
949 //-----------------------------------------------------------------------------
950 //! Converts the data type of the cvMat
951 void CVImage::convertTo(int cvDataType)
952 {
953  _cvMat.convertTo(_cvMat, cvDataType);
954  _format = cvType2glPixelFormat(cvDataType);
956  _bytesPerLine = bytesPerLine((uint)_cvMat.cols,
957  _format,
958  _cvMat.isContinuous());
959  _bytesPerImage = _bytesPerLine * (uint)_cvMat.rows;
960 }
961 //-----------------------------------------------------------------------------
962 //! Flip X coordinates used to make JPEGs from top-left to bottom-left images.
964 {
965  if (_cvMat.cols > 0 && _cvMat.rows > 0)
966  {
967  CVMat dst = CVMat(_cvMat.rows, _cvMat.cols, _cvMat.type());
968  cv::flip(_cvMat, dst, 1);
969  _cvMat = dst;
970  }
971 }
972 //-----------------------------------------------------------------------------
973 //! Flip Y coordinates used to make JPEGs from top-left to bottom-left images.
975 {
976  if (_cvMat.cols > 0 && _cvMat.rows > 0)
977  {
978  CVMat dst = CVMat(_cvMat.rows, _cvMat.cols, _cvMat.type());
979  cv::flip(_cvMat, dst, 0);
980  _cvMat = dst;
981  }
982 }
983 //-----------------------------------------------------------------------------
984 //! Fills the image with a certain rgb color
985 void CVImage::fill(uchar r, uchar g, uchar b)
986 {
987  switch (_format)
988  {
989  case PF_rgb:
990  _cvMat.setTo(CVVec3b(r, g, b));
991  break;
992  case PF_bgr:
993  _cvMat.setTo(CVVec3b(b, g, r));
994  break;
995  default: Utils::exitMsg("SLProject", "CVImage::fill(r,g,b): Wrong format!", __LINE__, __FILE__);
996  }
997 }
998 //-----------------------------------------------------------------------------
999 //! Fills the image with a certain rgba color
1000 void CVImage::fill(uchar r, uchar g, uchar b, uchar a)
1001 {
1002  switch (_format)
1003  {
1004  case PF_rgba:
1005  _cvMat.setTo(CVVec4b(r, g, b, a));
1006  break;
1007  case PF_bgra:
1008  _cvMat.setTo(CVVec4b(b, g, r, a));
1009  break;
1010  default: Utils::exitMsg("SLProject", "CVImage::fill(r,g,b,a): Wrong format!", __LINE__, __FILE__);
1011  }
1012 }
1013 //-----------------------------------------------------------------------------
1014 void CVImage::crop(float targetWdivH, int& cropW, int& cropH)
1015 {
1016 
1017  float inWdivH = (float)_cvMat.cols / (float)_cvMat.rows;
1018  // viewportWdivH is negative the viewport aspect will be the same
1019  float outWdivH = targetWdivH < 0.0f ? inWdivH : targetWdivH;
1020 
1021  cropH = 0; // crop height in pixels of the source image
1022  cropW = 0; // crop width in pixels of the source image
1023  if (Utils::abs(inWdivH - outWdivH) > 0.01f)
1024  {
1025  int width = 0; // width in pixels of the destination image
1026  int height = 0; // height in pixels of the destination image
1027  int wModulo4;
1028  int hModulo4;
1029 
1030  if (inWdivH > outWdivH) // crop input image left & right
1031  {
1032  width = (int)((float)_cvMat.rows * outWdivH);
1033  height = _cvMat.rows;
1034  cropW = (int)((float)(_cvMat.cols - width) * 0.5f);
1035 
1036  // Width must be devidable by 4
1037  wModulo4 = width % 4;
1038  if (wModulo4 == 1) width--;
1039  if (wModulo4 == 2)
1040  {
1041  cropW++;
1042  width -= 2;
1043  }
1044  if (wModulo4 == 3) width++;
1045  }
1046  else // crop input image at top & bottom
1047  {
1048  width = _cvMat.cols;
1049  height = (int)((float)_cvMat.cols / outWdivH);
1050  cropH = (int)((float)(_cvMat.rows - height) * 0.5f);
1051 
1052  // Height must be devidable by 4
1053  hModulo4 = height % 4;
1054  if (hModulo4 == 1) height--;
1055  if (hModulo4 == 2)
1056  {
1057  cropH++;
1058  height -= 2;
1059  }
1060  if (hModulo4 == 3) height++;
1061  }
1062 
1063  _cvMat(cv::Rect(cropW, cropH, width, height)).copyTo(_cvMat);
1064  // imwrite("AfterCropping.bmp", lastFrame);
1065  }
1066 }
1067 //-----------------------------------------------------------------------------
1068 //! Returns the cv::Mat.type()) as string
1069 string CVImage::typeString(int cvMatTypeInt)
1070 {
1071  // 7 base types, with five channel options each (none or C1, ..., C4)
1072  // clang-format off
1073  int numImgTypes = 35;
1074  int enum_ints[] = {CV_8U, CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4,
1075  CV_8S, CV_8SC1, CV_8SC2, CV_8SC3, CV_8SC4,
1076  CV_16U, CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4,
1077  CV_16S, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4,
1078  CV_32S, CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4,
1079  CV_32F, CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4,
1080  CV_64F, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4};
1081 
1082  string enum_strings[] = {"CV_8U", "CV_8UC1", "CV_8UC2", "CV_8UC3", "CV_8UC4",
1083  "CV_8S", "CV_8SC1", "CV_8SC2", "CV_8SC3", "CV_8SC4",
1084  "CV_16U", "CV_16UC1", "CV_16UC2", "CV_16UC3", "CV_16UC4",
1085  "CV_16S", "CV_16SC1", "CV_16SC2", "CV_16SC3", "CV_16SC4",
1086  "CV_32S", "CV_32SC1", "CV_32SC2", "CV_32SC3", "CV_32SC4",
1087  "CV_32F", "CV_32FC1", "CV_32FC2", "CV_32FC3", "CV_32FC4",
1088  "CV_64F", "CV_64FC1", "CV_64FC2", "CV_64FC3", "CV_64FC4"};
1089  // clang-format on
1090 
1091  for (int i = 0; i < numImgTypes; i++)
1092  {
1093  if (cvMatTypeInt == enum_ints[i]) return enum_strings[i];
1094  }
1095  return "unknown image type";
1096 }
1097 //-----------------------------------------------------------------------------
CVPixelFormatGL
Pixel format according to OpenGL pixel format defines.
Definition: CVImage.h:24
@ PF_rgb_integer
Definition: CVImage.h:42
@ PF_rgba16f
Definition: CVImage.h:52
@ PF_luminance
Definition: CVImage.h:28
@ PF_bgr_integer
Definition: CVImage.h:44
@ PF_alpha
Definition: CVImage.h:27
@ PF_rgba_integer
Definition: CVImage.h:43
@ PF_green
Definition: CVImage.h:31
@ PF_rg_integer
Definition: CVImage.h:40
@ PF_red
Definition: CVImage.h:34
@ PF_luminance_alpha
Definition: CVImage.h:29
@ PF_rgb
Definition: CVImage.h:36
@ PF_bgra_integer
Definition: CVImage.h:45
@ PF_rg
Definition: CVImage.h:35
@ PF_depth_component
Definition: CVImage.h:33
@ PF_bgra
Definition: CVImage.h:39
@ PF_unknown
Definition: CVImage.h:25
@ PF_rgba
Definition: CVImage.h:37
@ PF_yuv_420_888
Definition: CVImage.h:26
@ PF_r32f
Definition: CVImage.h:47
@ PF_bgr
Definition: CVImage.h:38
@ PF_r16f
Definition: CVImage.h:46
@ PF_rg16f
Definition: CVImage.h:48
@ PF_red_integer
Definition: CVImage.h:41
@ PF_rgb32f
Definition: CVImage.h:51
@ PF_rgba32f
Definition: CVImage.h:50
@ PF_blue
Definition: CVImage.h:32
@ PF_rg32f
Definition: CVImage.h:49
@ PF_intensity
Definition: CVImage.h:30
@ PF_rgb16f
Definition: CVImage.h:53
cv::Vec4f CVVec4f
Definition: CVTypedefs.h:54
vector< cv::Vec3f > CVVVec3f
Definition: CVTypedefs.h:85
vector< cv::Vec4f > CVVVec4f
Definition: CVTypedefs.h:86
cv::Vec3f CVVec3f
Definition: CVTypedefs.h:52
cv::Vec2b CVVec2b
Definition: CVTypedefs.h:47
cv::Vec4b CVVec4b
Definition: CVTypedefs.h:49
cv::Mat CVMat
Definition: CVTypedefs.h:38
cv::Vec3b CVVec3b
Definition: CVTypedefs.h:48
@ IOK_image
Definition: SLFileStorage.h:40
OpenCV image class with the same interface as the former SLImage class.
Definition: CVImage.h:64
uint _bytesPerPixel
Number of bytes per pixel.
Definition: CVImage.h:145
void resize(int width, int height)
Definition: CVImage.cpp:938
CVVec4f getPixelf(float x, float y)
Definition: CVImage.cpp:788
void setPixeliRGB(int x, int y, CVVec3f color)
setPixeli sets the RGB pixel color at the integer pixel coordinate x, y
Definition: CVImage.cpp:893
void fill(uchar r, uchar g, uchar b)
Fills the image with a certain rgb color.
Definition: CVImage.cpp:985
uint width()
Definition: CVImage.h:125
~CVImage()
Definition: CVImage.cpp:95
void flipX()
Flip X coordinates used to make JPEGs from top-left to bottom-left images.
Definition: CVImage.cpp:963
uint bytesInFile()
Definition: CVImage.h:130
uchar * data()
Definition: CVImage.h:123
CVPixelFormatGL _format
OpenGL pixel format.
Definition: CVImage.h:144
void setPixeliRGBA(int x, int y, CVVec4f color)
setPixeli sets the RGBA pixel color at the integer pixel coordinate x, y
Definition: CVImage.cpp:921
string formatString()
Definition: CVImage.h:132
void clearData()
Deletes all data and resets the image parameters.
Definition: CVImage.cpp:102
uint _bytesPerLine
Number of bytes per line (stride)
Definition: CVImage.h:146
static string typeString(int cvMatTypeInt)
Returns the cv::Mat.type()) as string.
Definition: CVImage.cpp:1069
void savePNG(const string &filename, int compressionLevel=6, bool flipY=true, bool convertBGR2RGB=true)
Save as PNG at a certain compression level (0-9)
Definition: CVImage.cpp:637
CVMat cvMat() const
Definition: CVImage.h:122
CVPixelFormatGL format()
Definition: CVImage.h:131
static int glPixelFormat2cvType(CVPixelFormatGL pixelFormatGL)
Converts OpenGL pixel format to OpenCV mat type.
Definition: CVImage.cpp:563
uint _bytesPerImage
Number of bytes per image.
Definition: CVImage.h:147
static CVPixelFormatGL cvType2glPixelFormat(int cvType)
Converts OpenCV mat type to OpenGL pixel format.
Definition: CVImage.cpp:522
uint bytesPerImage()
Definition: CVImage.h:129
uint bytesPerPixel()
Definition: CVImage.h:127
uint height()
Definition: CVImage.h:126
CVVec4f getPixeli(int x, int y)
getPixeli returns the pixel color at the integer pixel coordinate x, y
Definition: CVImage.cpp:710
void saveJPG(const string &filename, int compressionLevel=95, bool flipY=true, bool convertBGR2RGB=true)
Save as JPG at a certain compression level (0-100)
Definition: CVImage.cpp:675
string _path
path on the filesystem
Definition: CVImage.h:149
uint bytesPerLine()
Definition: CVImage.h:128
CVMat _cvMat
OpenCV mat matrix image type.
Definition: CVImage.h:143
void convertTo(int cvDataType)
Converts the data type of the cvMat.
Definition: CVImage.cpp:951
bool allocate(int width, int height, CVPixelFormatGL pixelFormatGL, bool isContinuous=true)
Memory allocation function.
Definition: CVImage.cpp:119
void flipY()
Flip Y coordinates used to make JPEGs from top-left to bottom-left images.
Definition: CVImage.cpp:974
void load(const string &filename, bool flipVertical=true, bool loadGrayscaleIntoAlpha=false)
Loads the image with the appropriate image loader.
Definition: CVImage.cpp:379
void setPixeli(int x, int y, CVVec4f color)
setPixeli sets the RGB pixel color at the integer pixel coordinate x, y
Definition: CVImage.cpp:834
uint _bytesInFile
Number of bytes in file.
Definition: CVImage.h:148
void crop(float targetWdivH, int &cropW, int &cropH)
Definition: CVImage.cpp:1014
string path()
Definition: CVImage.h:133
string _name
Image name (e.g. from the filename)
Definition: CVImage.h:142
CVImage()
Default constructor.
Definition: CVImage.cpp:22
SLIOBuffer readIntoBuffer(std::string path, SLIOStreamKind kind)
Reads an entire file into memory.
Utils provides utilities for string & file handling, logging and math functions.
Definition: Averaged.h:22
T sign(T a)
Definition: Utils.h:245
T abs(T a)
Definition: Utils.h:249
unsigned int getFileSize(const string &pathfilename)
Returns the file size in bytes.
Definition: Utils.cpp:912
string getFileName(const string &pathFilename)
Returns the filename of path-filename string.
Definition: Utils.cpp:580
string getPath(const string &pathFilename)
Returns the path w. '\' of path-filename string.
Definition: Utils.cpp:392
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135
T fract(T a)
Definition: Utils.h:248
string getFileExt(const string &filename)
Returns the file extension without dot in lower case.
Definition: Utils.cpp:629
Utility struct that holds a pointer and its length.
Definition: SLFileStorage.h:28
void deallocate()
Deallocates the data owned by the buffer.
size_t size
Definition: SLFileStorage.h:30
unsigned char * data
Definition: SLFileStorage.h:29