PICCANTE  0.4
The hottest HDR imaging library!
image.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_IMAGE_HPP
19 #define PIC_IMAGE_HPP
20 
21 #include <string>
22 #include <vector>
23 #include <algorithm>
24 #include <random>
25 #include <math.h>
26 #include <float.h>
27 #include <limits>
28 #include <string>
29 
30 #include "base.hpp"
31 #include "util/compability.hpp"
32 #include "util/bbox.hpp"
33 #include "util/buffer.hpp"
34 #include "util/dynamic_range.hpp"
35 #include "util/math.hpp"
36 #include "util/array.hpp"
37 #include "util/indexed_array.hpp"
38 #include "util/std_util.hpp"
39 
40 //IO formats
41 #include "io/bmp.hpp"
42 #include "io/exr.hpp"
43 #include "io/exr_tiny.hpp"
44 #include "io/hdr.hpp"
45 #include "io/pfm.hpp"
46 #include "io/ppm.hpp"
47 #include "io/pgm.hpp"
48 #include "io/tmp.hpp"
49 #include "io/tga.hpp"
50 #include "io/vol.hpp"
51 #include "io/stb.hpp"
52 #include "io/exif.hpp"
53 #include "util/io.hpp"
54 
55 namespace pic {
56 
60 class Image
61 {
62 protected:
63 
67  void setNULL();
68 
69  //applied rendering values
70  bool flippedEXR;
72  bool notOwned;
73 
75 
77 
78 public:
79  float exposure;
81 
83 
85 
86  std::string nameFile;
87 
91  float *data;
92 
96  unsigned char *dataUC;
97 
101  unsigned char *dataRGBE;
102 
103  //Half-precision encoding
104 #ifdef PIC_ENABLE_OPEN_EXR
105  Imf::Rgba *dataEXR;
106 #endif
107 
111  Image();
112 
118  Image(Image *imgIn, bool deepCopy);
119 
132  Image(std::string nameFile, LDR_type typeLoad);
133 
140  Image(int width, int height, int channels);
141 
147  Image(float *color, int channels);
148 
159  Image(int frames, int width, int height, int channels, float *data);
160 
164  ~Image();
165 
173  void allocate(int width, int height, int channels, int frames);
174 
179  void allocateAux();
180 
184  void release();
185 
193  void copySubImage(Image *imgIn, int startX, int startY);
194 
199  void scaleCosine();
200 
204  void flipH()
205  {
207  }
208 
212  void flipV()
213  {
215  }
216 
220  void flipHV()
221  {
224  }
225 
229  void flipVH()
230  {
233  }
234 
238  void rotate90CCW()
239  {
241  allocateAux();
242  }
243 
247  void rotate90CW()
248  {
250  allocateAux();
251  }
252 
258  {
259  return sqrtf(widthf * widthf + heightf * heightf);
260  }
261 
265  void setZero();
266 
271  void setRand(unsigned int seed);
272 
279  bool isValid();
280 
288  bool isSimilarType(const Image *img);
289 
294  void assign(const Image *imgIn);
295 
301  void blend(Image *img, Image *weight);
302 
309  void minimum(Image *img);
310 
317  void maximum(Image *img);
318 
323  void applyFunction(float(*func)(float));
324 
329  void applyFunctionParam(float(*func)(float, std::vector<float>&), std::vector<float> &param);
330 
335  BBox getFullBox();
336 
346  float *getMaxVal(BBox *box, float *ret);
347 
357  float *getMinVal(BBox *box, float *ret);
358 
368  float *getLogMeanVal(BBox *box, float *ret);
369 
379  float *getSumVal(BBox *box, float *ret);
380 
390  float *getMeanVal(BBox *box, float *ret);
391 
402  float *getMomentsVal(int x0, int y0, int radius, float *ret);
403 
413  float *getVarianceVal(float *meanVal, BBox *box, float *ret);
414 
424  float *getCovMtxVal(float *meanVal, BBox *box, float *ret);
425 
437  float *getPercentileVal(float percentile, BBox *box, float *ret);
438 
439 
450  float *getMedVal( BBox *box, float *ret);
451 
458  float getDynamicRange(bool bRobust, float percentile);
459 
464  unsigned char *getdataUC()
465  {
466  return dataUC;
467  }
468 
475  float *getColorSamples(float *samples, int &nSamples, float percentage);
476 
481  int size() const
482  {
483  return height * width * channels * frames;
484  }
485 
490  int sizeFrame() const
491  {
492  return height * width * channels;
493  }
494 
499  int nPixels() const
500  {
501  return height * width * frames;
502  }
503 
512  bool checkCoordinates(int x, int y, int z = 0)
513  {
514  return (x > -1) && (x < width) && (y > -1) && (y < height) &&
515  (z > -1) && (z < frames);
516  }
517 
525  void convertFromMask(bool *mask, int width, int height);
526 
535  bool *convertToMask(float *color, float threshold, bool cmp, bool *mask);
536 
542  {
543  return flippedEXR;
544  }
545 
550  void removeSpecials();
551 
557  void clamp(float a, float b);
558 
564  {
566  ystride = width * channels;
567  xstride = channels;
568  }
569 
577  float *operator()(int x, int y, int t)
578  {
579  return data + CLAMP(t, frames) * tstride +
580  CLAMP(x, width) * xstride +
581  CLAMP(y, height) * ystride;
582  }
583 
590  float *operator()(int x, int y)
591  {
592  return data + CLAMP(x, width) * xstride +
593  CLAMP(y, height) * ystride;
594  }
595 
603  float *operator()(float x, float y)
604  {
605  int ix = CLAMP(int(floorf(x * width)), width);
606  int iy = CLAMP(int(floorf(y * height)), height);
607  return data + ix * xstride + iy * ystride;
608  }
609 
619  float *getLL(float x, float y, float z)
620  {
621  float xf = 1.0f - ((atan2f(z, -x) * C_INV_PI) * 0.5f + 0.5f);
622  float yf = (acosf(y) * C_INV_PI);
623 
624  int ix = CLAMP(int(floorf(x * width)), width);
625  int iy = CLAMP(int(floorf(y * height)), height);
626 
627  return data + ix * xstride + iy * ystride;
628  }
629 
638  void getNormalizedCoords(int x, int y, float &nx, float &ny)
639  {
640  nx = float(x) / width1f;
641  ny = float(y) / height1f;
642  }
643 
650  int getAddress(int x, int y)
651  {
652  x = CLAMP(x, width);
653  y = CLAMP(y, height);
654 
655  return x * xstride + y * ystride;
656  }
657 
665  int getAddress(int x, int y, int t)
666  {
667  x = CLAMP(x, width);
668  y = CLAMP(y, height);
669  t = CLAMP(t, frames);
670 
671  return x * xstride + y * ystride + t * tstride;
672  }
673 
680  void reverseAddress(int ind, int &x, int &y)
681  {
682  ind = ind / channels;
683  y = ind / width;
684  x = ind - (y * width);
685  }
686 
693 
698  void allocateSimilarTo(Image *img);
699 
704  Image *clone() const;
705 
720  bool Read (std::string nameFile, LDR_type typeLoad);
721 
739  bool Write(std::string nameFile, LDR_type typeWrite, int writerCounter);
740 
741 
747  {
748  this->notOwned = notOwned;
749  }
750 
755  void operator =(const Image &a);
756 
761  void operator =(const float &a);
762 
767  void operator +=(const float &a);
768 
774  Image operator +(const float &a) const;
775 
780  void operator +=(const Image &a);
781 
787  Image operator +(const Image &a) const;
788 
793  void operator *=(const float &a);
794 
800  Image operator *(const float &a) const;
801 
806  void operator *=(const Image &a);
807 
813  Image operator *(const Image &a) const;
814 
819  void operator -=(const float &a);
820 
826  Image operator -(const float &a) const;
827 
832  void operator -=(const Image &a);
833 
839  Image operator -(const Image &a) const;
840 
845  void operator /=(const float &a);
846 
852  Image operator /(const float &a) const;
853 
858  void operator /=(const Image &a);
859 
865  Image operator /(const Image &a) const;
866 
871  float *sort()
872  {
873  if(!isValid()) {
874  return NULL;
875  }
876 
877  int size_i = size();
878  float *tmp = new float[size_i];
879  memcpy(tmp, data, sizeof(float) * size_i);
880  std::sort(tmp, tmp + size_i);
881  return tmp;
882  }
883 };
884 
886 {
887  nameFile = "";
888  notOwned = false;
889 
890  alpha = -1;
891  tstride = -1;
892  ystride = -1;
893  xstride = -1;
894  width = -1;
895  height = -1;
896  frames = -1;
897  depth = -1;
898  channels = -1;
899 
900  channelsf = -1.0f;
901  widthf = -1.0f;
902  heightf = -1.0f;
903  width1f = -1.0f;
904  height1f = -1.0f;
905  framesf = -1.0f;
906  frames1f = -1.0f;
907 
908  data = NULL;
909  dataUC = NULL;
910  dataRGBE = NULL;
911  typeLoad = LT_NONE;
912 
913 #ifdef PIC_ENABLE_OPEN_EXR
914  dataEXR = NULL;
915 #endif
916 
917  flippedEXR = false;
918 
919  readerCounter = 0;
920  exposure = 1.0f;
921 }
922 
924 {
925  setNULL();
926 }
927 
928 PIC_INLINE Image::Image(Image *imgIn, bool deepCopy = true)
929 {
930  setNULL();
931 
932  if(imgIn == NULL) {
933  return;
934  }
935 
936  if(deepCopy) {
937  assign(imgIn);
938  } else {
939  width = imgIn->width;
940  height = imgIn->height;
941  channels = imgIn->channels;
942  frames = imgIn->frames;
943 
944  widthf = imgIn->widthf;
945  heightf = imgIn->heightf;
946  channelsf = imgIn->channelsf;
947  framesf = imgIn->framesf;
948 
949  data = imgIn->data;
950  dataUC = imgIn->dataUC;
951  dataRGBE = imgIn->dataRGBE;
952 
953  #ifdef PIC_ENABLE_OPEN_EXR
954  dataRGBE = imgIn->dataRGBE;
955  #endif
956 
957  notOwned = true;
958  exposure = imgIn->exposure;
959  nameFile = imgIn->nameFile;
960  flippedEXR = imgIn->flippedEXR;
961  typeLoad = imgIn->typeLoad;
962 
963  allocateAux();
964  }
965 
966 }
967 
968 PIC_INLINE Image::Image(int width, int height, int channels = 3)
969 {
970  setNULL();
972 }
973 
974 PIC_INLINE Image::Image(int frames, int width, int height, int channels,
975  float *data = NULL)
976 {
977  setNULL();
978 
979  if(data == NULL) {
981  } else {
982  this->frames = frames;
983  this->channels = channels;
984  this->width = width;
985  this->height = height;
986  this->notOwned = true;
987  this->data = data;
988 
989  allocateAux();
990  }
991 }
992 
993 PIC_INLINE Image::Image(std::string nameFile, LDR_type typeLoad = LT_NOR_GAMMA)
994 {
995  setNULL();
997 }
998 
999 PIC_INLINE Image::Image(float *color, int channels)
1000 {
1001  typeLoad = LT_NONE;
1002  setNULL();
1003 
1004  if(color != NULL) {
1005  allocate(1, 1, channels, 1);
1006  memcpy(data, color, channels);
1007  }
1008 }
1009 
1011 {
1012  release();
1013 }
1014 
1016 {
1017  //release all allocated resources
1018  if(!notOwned) {
1019  data = delete_vec_s(data);
1022 
1023  #ifdef PIC_ENABLE_OPEN_EXR
1024  delete_vec_s(dataEXR);
1025  #endif
1026  }
1027 }
1028 
1029 PIC_INLINE void Image::allocate(int width, int height, int channels, int frames)
1030 {
1031  if(width < 1 || height < 1 || channels < 1 || frames < 1) {
1032  #ifdef PIC_DEBUG
1033  printf("Image::Allocate: not a valid image to be allocated.\n");
1034  #endif
1035  return;
1036  }
1037 
1038  if(this->width > 0 && this->height > 0 && this->channels > 0 &&
1039  this->frames > 0 && data != NULL) {
1040  #ifdef PIC_DEBUG
1041  printf("Image::Allocate: already allocated image.\n");
1042  #endif
1043  return;
1044  }
1045 
1046  this->frames = frames;
1047  this->channels = channels;
1048  this->width = width;
1049  this->height = height;
1050  this->notOwned = false;
1051 
1052  data = new float [size()];
1053 
1054  allocateAux();
1055 }
1056 
1058 {
1059  this->fullBox = getFullBox();
1060 
1061  this->depth = frames;
1062  this->widthf = float(width);
1063  this->width1f = float(width - 1);
1064  this->heightf = float(height);
1065  this->height1f = float(height - 1);
1066  this->channelsf = float(channels);
1067  this->framesf = float(frames);
1068  this->frames1f = float(frames -1);
1069 
1070  calculateStrides();
1071 }
1072 
1074 {
1075  BBox fullBox;
1076  fullBox.setBox(0, width, 0, height, 0, frames, width,
1077  height, frames);
1078 
1079  return fullBox;
1080 }
1081 
1082 PIC_INLINE void Image::assign(const Image *imgIn)
1083 {
1084  if(imgIn == NULL) {
1085  return;
1086  }
1087 
1088  if(!isSimilarType(imgIn)) {
1089  release();
1090  allocate(imgIn->width, imgIn->height, imgIn->channels, imgIn->frames);
1091  }
1092 
1093  exposure = imgIn->exposure;
1094  nameFile = imgIn->nameFile;
1095  typeLoad = imgIn->typeLoad;
1096  flippedEXR = imgIn->flippedEXR;
1097 
1098  memcpy(data, imgIn->data, size() * sizeof(float));
1099 }
1100 
1101 PIC_INLINE void Image::clamp(float a = 0.0f, float b = 1.0f)
1102 {
1103  int size_i = size();
1104 
1105  #pragma omp parallel for
1106  for(int i = 0; i < size_i; i++) {
1107  data[i] = CLAMPi(data[i], a, b);
1108  }
1109 }
1110 
1112 {
1113  int size_i = size();
1114 
1115  #pragma omp parallel for
1116  for(int i = 0; i < size_i; i++) {
1117  float val = data[i];
1118 
1119  if(isnan(val) || isinf(val)) {
1120  data[i] = 0.0f;
1121  }
1122  }
1123 }
1124 
1125 PIC_INLINE bool Image::isSimilarType(const Image *img)
1126 {
1127  if(img == NULL) {
1128  return false;
1129  }
1130 
1131  bool ret = (width == img->width) &&
1132  (height == img->height) &&
1133  (frames == img->frames) &&
1134  (channels == img->channels) &&
1135  (flippedEXR == img->flippedEXR);
1136 
1137 #ifdef PIC_DEBUG
1138 
1139  if(!ret) {
1140  printf("\nImage::isSimilarType: ERROR The two compared images are not similar.\n");
1141  }
1142 
1143 #endif
1144 
1145  return ret;
1146 }
1147 
1149 {
1150  return (width > 0) && (height > 0) && (channels > 0) && (frames > 0) &&
1151  (data != NULL);
1152 }
1153 
1154 PIC_INLINE void Image::copySubImage(Image *imgIn, int startX, int startY)
1155 {
1156  Buffer<float>::copySubBuffer(imgIn->data, imgIn->width, imgIn->height, imgIn->channels,
1157  startX, startY,
1158  data, width, height, channels);
1159 }
1160 
1162 {
1163  int half_h = height >> 1;
1164 
1165  #pragma omp parallel for
1166  for(int i = 0; i < height; i++) {
1167  float angle = C_PI * float(i - half_h) / float(height);
1168  float cosAng = MAX(cosf(angle), 0.0f);
1169 
1170  for(int j = 0; j < width; j++) {
1171  float *tmp_data = (*this)(j, i);
1172 
1173  for(int k = 0; k < channels; k++) {
1174  tmp_data[k] *= cosAng;
1175  }
1176  }
1177  }
1178 }
1179 
1180 PIC_INLINE void Image::applyFunction(float(*func)(float))
1181 {
1182  if(!isValid()) {
1183  return;
1184  }
1185 
1186  int size_i = size();
1187 
1188  #pragma omp parallel for
1189  for(int i = 0; i < size_i; i++) {
1190  data[i] = (*func)(data[i]);
1191  }
1192 }
1193 
1194 PIC_INLINE void Image::applyFunctionParam(float(*func)(float, std::vector<float>&), std::vector<float> &param)
1195 {
1196  if(!isValid()) {
1197  return;
1198  }
1199 
1200  int size_i = size();
1201 
1202  #pragma omp parallel for
1203  for(int i = 0; i < size_i; i++) {
1204  data[i] = (*func)(data[i], param);
1205  }
1206 }
1207 
1208 PIC_INLINE float *Image::getPercentileVal(float percentile, BBox *box, float *ret)
1209 {
1210  if(!isValid()) {
1211  return ret;
1212  }
1213 
1214  if(box == NULL) {
1215  box = &fullBox;
1216  }
1217 
1218  if(ret == NULL) {
1219  ret = new float[channels << 1];
1220  }
1221 
1222  int size_i = box->Size();
1223  float *dataTMP = new float[size_i];
1224 
1225  for(int ch = 0; ch < channels; ch++) {
1226  int counter = 0;
1227  for(int k = box->z0; k < box->z1; k++) {
1228  for(int j = box->y0; j < box->y1; j++) {
1229  for(int i = box->x0; i < box->x1; i++) {
1230  dataTMP[counter] = (*this)(i, j, k)[ch];
1231  counter++;
1232  }
1233  }
1234  }
1235 
1236  std::sort(dataTMP, dataTMP + size_i);
1237 
1238  int size_i_t = size_i - 1;
1239  int index_r = ch << 1;
1240 
1241  float index_f;
1242  int index;
1243 
1244  float size_i_t_f = float(size_i_t);
1245 
1246  index_f = percentile * size_i_t_f;
1247  index = CLAMPi(int(index_f), 0, size_i_t);
1248  ret[index_r ] = dataTMP[index];
1249 
1250  index_f = (1.0f - percentile) * size_i_t_f;
1251  index = CLAMPi(int(index_f), 0, size_i_t);
1252  ret[index_r + 1] = dataTMP[index];
1253  }
1254 
1255  delete[] dataTMP;
1256 
1257  return ret;
1258 }
1259 
1260 PIC_INLINE float *Image::getMedVal(BBox *box, float *ret)
1261 {
1262  return getPercentileVal(0.5f, box, ret);
1263 }
1264 
1265 PIC_INLINE float Image::getDynamicRange(bool bRobust = false, float percentile = 0.99f)
1266 {
1267  if(!isValid()) {
1268  return -1.0f;
1269  }
1270 
1271  if(bRobust) {
1272  if(percentile <= 0.5f) {
1273  percentile = 0.99f;
1274  }
1275 
1276  float percentile_low = 1.0f - percentile;
1277 
1278  float *values = getPercentileVal(percentile_low, NULL, NULL);
1279  float min_val = values[0];
1280  float max_val = values[1];
1281 
1282  if(min_val > 0.0f) {
1283  return max_val / min_val;
1284  } else {
1285  if(percentile > 0.5f) {
1286  return getDynamicRange(true, percentile * 0.99f);
1287  } else {
1288  return 0.0f;
1289  }
1290  }
1291  } else {
1292  float ret = -1.0f;
1293 
1294  float *min_val_v = getMinVal(NULL, NULL);
1295  float *max_val_v = getMaxVal(NULL, NULL);
1296 
1297  int ind;
1298  float min_val = Arrayf::getMin(min_val_v, channels, ind);
1299  float max_val = Arrayf::getMax(max_val_v, channels, ind);
1300 
1301  if(min_val <= 0.0f) {
1302  IntCoord coord;
1304  min_val = IndexedArray<float>::min(data, coord);
1305 
1306  if(min_val != max_val) {
1307  if(max_val > min_val) {
1308  ret = max_val / min_val;
1309  } else {
1310  ret = -2.0f;
1311  }
1312  } else {
1313  ret = 0.0f;
1314  }
1315  }
1316 
1317  delete_vec_s(min_val_v);
1318  delete_vec_s(max_val_v);
1319 
1320  return ret;
1321  }
1322 }
1323 
1324 PIC_INLINE void Image::blend(Image *img, Image *weight)
1325 {
1326  if(img == NULL || weight == NULL) {
1327  return;
1328  }
1329 
1330  if( (weight->channels != 1) &&
1331  (weight->channels != img->channels)) {
1332  return;
1333  }
1334 
1335  int size = height * width;
1336 
1337  #pragma omp parallel for
1338  for(int ind = 0; ind < size; ind++) {
1339  int i = ind * channels;
1340 
1341  int indx_w = ind * weight->channels;
1342  //int indx_w = i_w;// + (j % weight->channels);
1343  float w0 = weight->data[indx_w];
1344  float w1 = 1.0f - w0;
1345 
1346  for(int j = 0; j < channels; j++) {
1347  int indx = i + j;
1348 
1349  data[indx] = data[indx] * w0 + img->data[indx] * w1;
1350  }
1351  }
1352 }
1353 
1354 PIC_INLINE void Image::minimum(Image *img)
1355 {
1356  if(!isValid() || !isSimilarType(img)) {
1357  return;
1358  }
1359 
1360  int n = size();
1361 
1362  #pragma omp parallel for
1363 
1364  for(int i = 0; i < n; i++) {
1365  data[i] = data[i] > img->data[i] ? img->data[i] : data[i];
1366  }
1367 }
1368 
1369 PIC_INLINE void Image::maximum(Image *img)
1370 {
1371  if(!isValid() || !isSimilarType(img)) {
1372  return;
1373  }
1374 
1375  int n = size();
1376 
1377  #pragma omp parallel for
1378  for(int i = 0; i < n; i++) {
1379  data[i] = data[i] < img->data[i] ? img->data[i] : data[i];
1380  }
1381 }
1382 
1384 {
1385  if(!isValid()) {
1386  return;
1387  }
1388 
1389  Buffer<float>::assign(data, size(), 0.0f);
1390 }
1391 
1392 PIC_INLINE void Image::setRand(unsigned int seed = 1)
1393 {
1394  if(!isValid()) {
1395  return;
1396  }
1397 
1398  std::mt19937 m(seed);
1399  int n = size();
1400 
1401  for(int i = 0; i < n; i++) {
1402  data[i] = float(m()) / 4294967295.0f;
1403  }
1404 }
1405 
1406 PIC_INLINE float *Image::getMaxVal(BBox *box = NULL, float *ret = NULL)
1407 {
1408  if(!isValid()) {
1409  return ret;
1410  }
1411 
1412  if(box == NULL) {
1413  box = new BBox(width, height, frames);
1414  }
1415 
1416  if(ret == NULL) {
1417  ret = new float[channels];
1418  }
1419 
1420  for(int l = 0; l < channels; l++) {
1421  ret[l] = -FLT_MAX;
1422  }
1423 
1424  for(int k = box->z0; k < box->z1; k++) {
1425  for(int j = box->y0; j < box->y1; j++) {
1426  for(int i = box->x0; i < box->x1; i++) {
1427  float *tmp_data = (*this)(i, j, k);
1428 
1429  for(int l = 0; l < channels; l++) {
1430  ret[l] = ret[l] < tmp_data[l] ? tmp_data[l] : ret[l];
1431  }
1432  }
1433  }
1434  }
1435 
1436  return ret;
1437 }
1438 
1439 PIC_INLINE float *Image::getMinVal(BBox *box = NULL, float *ret = NULL)
1440 {
1441  if(!isValid()) {
1442  return ret;
1443  }
1444 
1445  if(box == NULL) {
1446  box = new BBox(width, height, frames);
1447  }
1448 
1449  if(ret == NULL) {
1450  ret = new float[channels];
1451  }
1452 
1453  for(int l = 0; l < channels; l++) {
1454  ret[l] = FLT_MAX;
1455  }
1456 
1457  for(int k = box->z0; k < box->z1; k++) {
1458  for(int j = box->y0; j < box->y1; j++) {
1459  for(int i = box->x0; i < box->x1; i++) {
1460  float *tmp_data = (*this)(i, j, k);
1461 
1462  for(int l = 0; l < channels; l++) {
1463  ret[l] = ret[l] > tmp_data[l] ? tmp_data[l] : ret[l];
1464  }
1465  }
1466  }
1467  }
1468 
1469  return ret;
1470 }
1471 
1472 PIC_INLINE float *Image::getSumVal(BBox *box = NULL, float *ret = NULL)
1473 {
1474  if(!isValid()) {
1475  return ret;
1476  }
1477 
1478  if(box == NULL) {
1479  box = &fullBox;
1480  }
1481 
1482  if(ret == NULL) {
1483  ret = new float[channels];
1484  }
1485 
1486  Arrayf::assign(0.0f, ret, channels);
1487 
1488  for(int k = box->z0; k < box->z1; k++) {
1489  for(int j = box->y0; j < box->y1; j++) {
1490  for(int i = box->x0; i < box->x1; i++) {
1491  float *tmp_data = (*this)(i, j, k);
1492 
1493  Arrayf::add(tmp_data, channels, ret);
1494  }
1495  }
1496  }
1497 
1498  return ret;
1499 }
1500 
1501 PIC_INLINE float *Image::getMeanVal(BBox *box = NULL, float *ret = NULL)
1502 {
1503  if(!isValid()) {
1504  return ret;
1505  }
1506 
1507  if(box == NULL) {
1508  box = &fullBox;
1509  }
1510 
1511  ret = getSumVal(box, ret);
1512 
1513  float totf = float(box->Size());
1514 
1515  Arrayf::div(ret, channels, totf);
1516 
1517  return ret;
1518 }
1519 
1520 PIC_INLINE float *Image::getMomentsVal(int x0, int y0, int radius, float *ret = NULL)
1521 {
1522  if(!isValid()) {
1523  return ret;
1524  }
1525 
1526  int channels_2 = channels << 1;
1527 
1528  if(ret == NULL) {
1529  ret = new float[channels_2];
1530  }
1531 
1532  Arrayf::assign(0.0f, ret, channels_2);
1533 
1534  for(int j = -radius; j <= radius; j++) {
1535  int y = y0 + j;
1536 
1537  for(int i = -radius; i <= radius; i++) {
1538  int x = x0 + i;
1539 
1540  float *tmp_data = (*this)(x, y);
1541 
1542  for(int l = 0; l < channels_2; l += 2) {
1543  ret[l ] += j * tmp_data[l];
1544  ret[l + 1] += i * tmp_data[l];
1545  }
1546  }
1547  }
1548 
1549  return ret;
1550 }
1551 
1552 PIC_INLINE float *Image::getVarianceVal(float *meanVal = NULL,
1553  BBox *box = NULL,
1554  float *ret = NULL)
1555 {
1556  if(!isValid()) {
1557  return ret;
1558  }
1559 
1560  if(box == NULL) {
1561  box = &fullBox;
1562  }
1563 
1564  bool bDeleteMeanVal = false;
1565 
1566  if(meanVal == NULL) {
1567  meanVal = getMeanVal(box, NULL);
1568  bDeleteMeanVal = true;
1569  }
1570 
1571  if(ret == NULL) {
1572  ret = new float[channels];
1573  }
1574 
1575  Arrayf::assign(0.0f, ret, channels);
1576 
1577  for(int k = box->z0; k < box->z1; k++) {
1578  for(int j = box->y0; j < box->y1; j++) {
1579  for(int i = box->x0; i < box->x1; i++) {
1580  float *tmp_data = (*this)(i, j, k);
1581 
1582  for(int l = 0; l < channels; l++) {
1583  float tmp = tmp_data[l] - meanVal[l];
1584  ret[l] += tmp * tmp;
1585  }
1586  }
1587  }
1588  }
1589 
1590  float totf = float(box->Size() - 1);
1591 
1592  Arrayf::div(ret, channels, totf);
1593 
1594  if(bDeleteMeanVal) {
1595  delete[] meanVal;
1596  }
1597 
1598  return ret;
1599 }
1600 
1601 
1602 PIC_INLINE float *Image::getCovMtxVal(float *meanVal, BBox *box, float *ret)
1603 {
1604  if(!isValid()) {
1605  return ret;
1606  }
1607 
1608  if(box == NULL) {
1609  box = &fullBox;
1610  }
1611 
1612  bool bMeanValAllocated = false;
1613 
1614  if(meanVal == NULL) {
1615  meanVal = getMeanVal(box, NULL);
1616  bMeanValAllocated = true;
1617  }
1618 
1619  int n = channels * channels;
1620 
1621  if(ret == NULL) {
1622  ret = new float[n];
1623  }
1624 
1625  Arrayf::assign(0.0f, ret, n);
1626 
1627  for(int k = box->z0; k < box->z1; k++) {
1628  for(int j = box->y0; j < box->y1; j++) {
1629  for(int i = box->x0; i < box->x1; i++) {
1630  float *tmp_data = (*this)(i, j, k);
1631 
1632  for(int l = 0; l < channels; l++) {
1633  float tmp1 = (tmp_data[l] - meanVal[l]);
1634 
1635  for(int m = 0; m < channels; m++) {
1636  float tmp2 = (tmp_data[m] - meanVal[m]);
1637 
1638  ret[l * channels + m] += tmp1 * tmp2;
1639  }
1640  }
1641  }
1642  }
1643  }
1644 
1645  float totf = float(box->Size() - 1);
1646 
1647  Arrayf::div(ret, n, totf);
1648 
1649  if(bMeanValAllocated) {
1650  delete[] meanVal;
1651  }
1652 
1653  return ret;
1654 }
1655 
1656 PIC_INLINE float *Image::getLogMeanVal(BBox *box = NULL, float *ret = NULL)
1657 {
1658  if(!isValid()) {
1659  return ret;
1660  }
1661 
1662  if(box == NULL) {
1663  box = &fullBox;
1664  }
1665 
1666  if(ret == NULL) {
1667  ret = new float[channels];
1668  }
1669 
1670  Arrayf::assign(0.0f, ret, channels);
1671 
1672  for(int k = box->z0; k < box->z1; k++) {
1673  for(int j = box->y0; j < box->y1; j++) {
1674  for(int i = box->x0; i < box->x1; i++) {
1675  float *tmp_data = (*this)(i, j, k);
1676 
1677  for(int l = 0; l < channels; l++) {
1678  ret[l] += logf(tmp_data[l] + 1e-6f);
1679  }
1680  }
1681  }
1682  }
1683 
1684  float totf = float(box->Size());
1685 
1686  for(int l = 0; l < channels; l++) {
1687  ret[l] = expf(ret[l] / totf);
1688  }
1689 
1690  return ret;
1691 }
1692 
1693 PIC_INLINE void Image::convertFromMask(bool *mask, int width, int height)
1694 {
1695  if((mask == NULL) || (width < 1) || (height < 1)) {
1696  return;
1697  }
1698 
1699  if(!isValid() || this->width != width || this->height != height) {
1700  allocate(width, height, 1, 1);
1701  }
1702 
1703  int size = (width * height);
1704 
1705  #pragma omp parallel for
1706  for(int i = 0; i < size; i++) {
1707  data[i] = mask[i] ? 1.0f : 0.0f;
1708  }
1709 }
1710 
1711 PIC_INLINE bool *Image::convertToMask(float *color = NULL, float threshold = 0.25f,
1712  bool cmp = true, bool *mask = NULL)
1713 {
1714  if(!isValid()) {
1715  return NULL;
1716  }
1717 
1718  bool bColorAllocated = false;
1719 
1720  if(color == NULL) {
1721  bColorAllocated = true;
1722  color = new float[channels];
1723 
1724  Arrayf::assign(0.0f, color, channels);
1725  }
1726 
1727  int n = width * height;
1728 
1729  if(mask == NULL) {
1730  mask = new bool[n];
1731  }
1732 
1733  float tmpThreshold = threshold * float(channels);
1734 
1735  #pragma omp parallel for
1736  for(int i = 0; i < n; i++) {
1737  int ind = i * channels;
1738 
1739  float val = 0.0f;
1740 
1741  for(int k = 0; k < channels; k++) {
1742  val += fabsf(data[ind + k] - color[k]);
1743  }
1744 
1745  bool bMask = val > tmpThreshold;
1746  mask[i] = cmp ? bMask : !bMask;
1747 
1748  /*
1749  if(cmp) {
1750  mask[i] = val > tmpThreshold;
1751  } else {
1752  mask[i] = val < tmpThreshold;
1753  }*/
1754  }
1755 
1756  if(bColorAllocated) {
1757  delete[] color;
1758  }
1759 
1760  return mask;
1761 }
1762 
1763 PIC_INLINE bool Image::Read(std::string nameFile,
1764  LDR_type typeLoad = LT_NOR_GAMMA)
1765 {
1766  this->nameFile = nameFile;
1767 
1768  this->typeLoad = typeLoad;
1769 
1770  LABEL_IO_EXTENSION label;
1771 
1772  bool bReturn = false;
1773 
1774  //read the image in an HDR format
1775  label = getLabelHDRExtension(nameFile);
1776 
1777  if(label != IO_NULL) {
1778  float *dataReader = NULL;
1779  float *tmp = NULL;
1780 
1781  if(data != NULL) {
1782  dataReader = &data[tstride * readerCounter];
1783 #ifdef PIC_ENABLE_OPEN_EXR
1784  dataEXR = new Imf::Rgba[width * height];
1785 #endif
1786  } else {
1787  channels = 3;
1788  }
1789 
1790  switch(label) {
1791  case IO_TMP:
1792  tmp = ReadTMP(nameFile, dataReader, width, height, channels, frames);
1793  break;
1794 
1795  case IO_HDR:
1796  tmp = ReadHDR(nameFile, dataReader, width, height);
1797  break;
1798 
1799  case IO_PFM:
1800  tmp = ReadPFM(nameFile, dataReader, width, height, channels);
1801  break;
1802 
1803  case IO_EXR:
1804 #ifdef PIC_ENABLE_OPEN_EXR
1805  tmp = ReadEXR(nameFile, dataReader, width, height, channels, dataEXR);
1806 #else
1807 #ifndef PIC_DISABLE_TINY_EXR
1808  tmp = ReadEXR(nameFile, dataReader, width, height, channels);
1809 #endif
1810 #endif
1811  break;
1812 
1813  case IO_VOL:
1814  tmp = ReadVOL(nameFile, dataReader, width, height, frames, channels);
1815  depth = frames;
1816  break;
1817 
1818  default:
1819  tmp = NULL;
1820  }
1821 
1822  if(tmp != NULL) {
1823  if(data == NULL) {
1824  data = tmp;
1825 
1826  if(frames <= 0) {
1827  frames = 1;
1828  }
1829  }
1830 
1831  allocateAux();
1832  bReturn = true;
1833  } else {
1834  bReturn = false;
1835  }
1836  } else {
1837  //read the image using an LDR codec
1838  label = getLabelLDRExtension(nameFile);
1839  unsigned char *dataReader = NULL;
1840  unsigned char *tmp = NULL;
1841  bool bExt = false;
1842 
1843  if(dataUC != NULL) {
1844  dataReader = dataUC;
1845  }
1846 
1847  switch(label) {
1848  case IO_BMP: {
1849  tmp = ReadBMP(nameFile, dataReader, width, height, channels);
1850  } break;
1851 
1852  case IO_PPM: {
1853  tmp = ReadPPM(nameFile, dataReader, width, height, channels);
1854  } break;
1855 
1856  case IO_PGM: {
1858  } break;
1859 
1860  case IO_TGA: {
1861  tmp = ReadTGA(nameFile, dataReader, width, height, channels);
1862  } break;
1863 
1864  case IO_JPG: {
1865  bExt = true;
1866 
1867  EXIFInfo info;
1868  readEXIF(nameFile, info);
1869  exposure = estimateAverageLuminance(info.exposureTime, info.aperture, info.iso);
1870 
1871  } break;
1872 
1873  case IO_PNG: {
1874  bExt = true;
1875  } break;
1876 
1877  default: {
1878  tmp = NULL;
1879  } break;
1880 
1881  }
1882 
1883  if(bExt) {
1884  tmp = ReadSTB(nameFile, width, height, channels);
1885  }
1886 
1887  if(tmp != NULL) { //move the handle where it's trackable
1888  if(dataUC == NULL) {
1889  dataUC = tmp;
1890  }
1891  }
1892 
1893  if(typeLoad == LT_LDR) {
1894  return dataUC != NULL;
1895  }
1896 
1897  float *tmpFloat = NULL;
1898 
1899  if(data != NULL) {
1900  tmpFloat = &data[tstride * readerCounter];
1901  }
1902 
1903  float *tmpConv = convertLDR2HDR(tmp, tmpFloat, sizeFrame(), typeLoad);
1904 
1906 
1907  if(tmpConv != NULL) {
1908  if(data == NULL) {
1909  data = tmpConv;
1910  frames = frames > 0 ? frames : 1;
1911  allocateAux();
1912  }
1913 
1914  bReturn = true;
1915  } else {
1916  bReturn = false;
1917  }
1918  }
1919 
1921  return bReturn;
1922 }
1923 
1924 PIC_INLINE bool Image::Write(std::string nameFile, LDR_type typeWrite = LT_NOR_GAMMA,
1925  int writerCounter = 0)
1926 {
1927  if(!isValid()) {
1928  return false;
1929  }
1930 
1931  LABEL_IO_EXTENSION label;
1932 
1933  //read an image in an HDR format
1934  label = getLabelHDRExtension(nameFile);
1935 
1936  if(label != IO_NULL) {
1937  float *dataWriter = NULL;
1938 
1939  if((writerCounter > 0) && (writerCounter < frames)) {
1940  dataWriter = &data[tstride * writerCounter];
1941  } else {
1942  dataWriter = data;
1943  }
1944 
1945  bool ret = false;
1946 
1947  switch(label) {
1948  case IO_TMP:
1949  ret = WriteTMP(nameFile, dataWriter, width, height, channels, frames);
1950  break;
1951 
1952  case IO_HDR:
1953  ret = WriteHDR(nameFile, dataWriter, width, height, channels);
1954  break;
1955 
1956  case IO_PFM:
1957  ret = WritePFM(nameFile, dataWriter, width, height, channels);
1958  break;
1959 
1960  case IO_EXR:
1961 #ifdef PIC_ENABLE_OPEN_EXR
1962  ret = WriteEXR(nameFile, dataWriter, width, height, channels);
1963 #else
1964 #ifndef PIC_DISABLE_TINY_EXR
1965  ret = WriteEXR(nameFile, dataWriter, width, height, channels);
1966 #endif
1967 #endif
1968  break;
1969 
1970  case IO_VOL:
1971  ret = WriteVOL(nameFile, dataWriter, width, height, frames, channels);
1972  break;
1973 
1974  default:
1975  ret = false;
1976  }
1977 
1978  return ret;
1979  } else {
1980  //write the image into an LDR format
1981  label = getLabelLDRExtension(nameFile);
1982 
1983  bool bExt = (label == IO_JPG) || (label == IO_PNG);
1984 
1985  //allocate memory: begin
1986  float *dataWriter = NULL;
1987 
1988  if((writerCounter > 0) && (writerCounter < frames)) {
1989  dataWriter = &data[tstride * writerCounter];
1990  } else {
1991  dataWriter = data;
1992  }
1993 
1994  dataUC = convertHDR2LDR(dataWriter, dataUC, sizeFrame(), typeWrite);
1995 
1996  /*
1997  if(dataUC == NULL) {
1998  dataUC = tmp;
1999  } else {
2000  dataUC = delete_vec_s(dataUC);
2001  dataUC = tmp;
2002  }
2003  //allocate memory: end
2004  */
2005 
2006  if(bExt) {
2008  } else {
2009  switch(label) {
2010  case IO_BMP:
2012  break;
2013 
2014  case IO_TGA:
2015  //values are stored with a vertical flip
2017 
2018  //values needs to be stored as BGR
2020 
2022  break;
2023 
2024  case IO_PPM:
2026  break;
2027 
2028  case IO_PGM:
2030  break;
2031 
2032  default:
2033  return false;
2034  }
2035  }
2036  }
2037 }
2038 
2040 {
2041  Image *ret = new Image(frames, width, height, channels);
2042  ret->flippedEXR = flippedEXR;
2043  ret->exposure = exposure;
2044  ret->alpha = alpha;
2045  return ret;
2046 }
2047 
2048 PIC_INLINE void Image::allocateSimilarTo(Image *img)
2049 {
2050  if(img != NULL) {
2051  if(img->isValid()) {
2052  allocate(img->width, img->height, img->channels, img->frames);
2053  }
2054  }
2055 }
2056 
2057 PIC_INLINE Image *Image::clone() const
2058 {
2059  Image *ret = new Image(frames, width, height, channels);
2060 
2061  ret->fullBox = fullBox;
2062  ret->flippedEXR = flippedEXR;
2063  ret->exposure = exposure;
2064  ret->nameFile = nameFile;
2065  ret->alpha = alpha;
2066  ret->typeLoad = typeLoad;
2067 
2068  memcpy(ret->data, data, width * height * channels * sizeof(float));
2069 
2070  return ret;
2071 }
2072 
2073 PIC_INLINE float* Image::getColorSamples(float *samples,
2074  int &nSamples,
2075  float percentage = 1.0f)
2076 {
2077  percentage = CLAMPi(percentage, 0.0f, 1.0f);
2078 
2079  int nTot = nPixels();
2080  nSamples = int(ceilf(float(nTot) * percentage));
2081 
2082  if(samples == NULL) {
2083  samples = new float[nSamples * channels];
2084  }
2085 
2086  int shift = 1;
2087 
2088  if(nSamples < nTot) {
2089  shift = nTot / nSamples;
2090  }
2091 
2092  for(int i = 0; i < nSamples; i++) {
2093  int index = i * channels;
2094  int index_d = index * shift;
2095 
2096  for(int j = 0; j < channels; j++) {
2097  samples[index + j] = data[index_d + j];
2098  }
2099  }
2100 
2101  return samples;
2102 }
2103 
2104 PIC_INLINE void Image::operator =(const Image &a)
2105 {
2106  this->assign(&a);
2107 }
2108 
2109 PIC_INLINE void Image::operator =(const float &a)
2110 {
2112 }
2113 
2114 PIC_INLINE void Image::operator +=(const float &a)
2115 {
2116  Buffer<float>::add(data, size(), a);
2117 }
2118 
2119 PIC_INLINE Image Image::operator +(const float &a) const
2120 {
2121  Image *out = this->clone();
2122  *out += a;
2123  return Image(out, false);
2124 }
2125 
2126 PIC_INLINE void Image::operator +=(const Image &a)
2127 {
2128  if(isSimilarType(&a)) {
2129  Buffer<float>::add(data, a.data, size());
2130  } else {
2131  if((nPixels() == a.nPixels()) && (a.channels == 1)) {
2133  }
2134  }
2135 
2136 }
2137 
2138 PIC_INLINE Image Image::operator +(const Image &a) const
2139 {
2140  Image *out = this->clone();
2141  *out += a;
2142  return Image(out, false);
2143 }
2144 
2145 PIC_INLINE void Image::operator *=(const float &a)
2146 {
2147  Buffer<float>::mul(data, size(), a);
2148 }
2149 
2150 PIC_INLINE Image Image::operator *(const float &a) const
2151 {
2152  Image *out = this->clone();
2153  *out *= a;
2154  return Image(out, false);
2155 }
2156 
2157 PIC_INLINE void Image::operator *=(const Image &a)
2158 {
2159  if(isSimilarType(&a)) {
2160  Buffer<float>::mul(data, a.data, size());
2161  } else {
2162  if((nPixels() == a.nPixels()) && (a.channels == 1)) {
2164  }
2165  }
2166 }
2167 
2168 PIC_INLINE Image Image::operator *(const Image &a) const
2169 {
2170  Image *out = this->clone();
2171  *out *= a;
2172  return Image(out, false);
2173 }
2174 
2175 PIC_INLINE void Image::operator -=(const float &a)
2176 {
2177  Buffer<float>::sub(data, size(), a);
2178 }
2179 
2180 PIC_INLINE Image Image::operator -(const float &a) const
2181 {
2182  Image *out = this->clone();
2183  *out -= a;
2184  return Image(out, false);
2185 }
2186 
2187 PIC_INLINE void Image::operator -=(const Image &a)
2188 {
2189  if(isSimilarType(&a)) {
2190  Buffer<float>::sub(data, a.data, size());
2191  } else {
2192  if((nPixels() == a.nPixels()) && (a.channels == 1)) {
2194  }
2195  }
2196 }
2197 
2198 PIC_INLINE Image Image::operator -(const Image &a) const
2199 {
2200  Image *out = this->clone();
2201  *out -= a;
2202  return Image(out, false);
2203 }
2204 
2205 PIC_INLINE void Image::operator /=(const float &a)
2206 {
2207  Buffer<float>::div(data, size(), a);
2208 }
2209 
2210 PIC_INLINE Image Image::operator /(const float &a) const
2211 {
2212  Image *out = this->clone();
2213  *out /= a;
2214  return Image(out, false);
2215 }
2216 
2217 PIC_INLINE void Image::operator /=(const Image &a)
2218 {
2219  if(isSimilarType(&a)) {
2220  Buffer<float>::div(data, a.data, size());
2221  } else {
2222  if((nPixels() == a.nPixels()) && (a.channels == 1)) {
2224  }
2225  }
2226 }
2227 
2228 PIC_INLINE Image Image::operator /(const Image &a) const
2229 {
2230  Image *out = this->clone();
2231  *out /= a;
2232  return Image(out, false);
2233 }
2234 
2235 } // end namespace pic
2236 
2237 #endif /* PIC_IMAGE_HPP */
2238 
static void rotate90CCW(T *buffer, int &width, int &height, int channels)
rotate90CCW rotates an image 90 CCW
Definition: buffer.hpp:508
static T * add(T *buffer, int n, T value)
add peforms addition
Definition: buffer.hpp:84
float * getCovMtxVal(float *meanVal, BBox *box, float *ret)
getCovMtxVal computes the convariance matrix for the current Image.
PIC_INLINE bool WriteTMP(std::string nameFile, float *data, int &width, int &height, int &channels, int &frames, bool bHeader=true)
WriteTMP writes a dump temp file.
Definition: tmp.hpp:101
The BBox class manages the creation of bounding boxes for images.
Definition: bbox.hpp:29
void reverseAddress(int ind, int &x, int &y)
reverseAddress computes (x, y) given a memory address
Definition: image.hpp:680
void operator*=(const float &a)
operator *=
static T getMax(T *data, int size, int &ind)
getMax
Definition: array.hpp:516
void allocate(int width, int height, int channels, int frames)
allocate allocates memory for the pixel buffer.
void assign(const Image *imgIn)
assign
int size() const
size computes the number of values.
Definition: image.hpp:481
Image operator+(const float &a) const
operator +
static T * sub(T *buffer, int n, T value)
sub
Definition: buffer.hpp:227
static T * mul(T *buffer, int n, T value)
mul multiplies a constant value
Definition: buffer.hpp:148
~Image()
Image destructor. This deallocates: data, dataUC, and dataRGBE.
float * operator()(int x, int y, int t)
operator () returns a pointer to a pixel at (x, y, t)
Definition: image.hpp:577
void flipVH()
flipVH flips vertically and horizontally the current image.
Definition: image.hpp:229
float * data
data is the main buffer where pixel values are stored.
Definition: image.hpp:91
void setZero()
setZero sets data to 0.0f.
int channels
Definition: image.hpp:80
void clamp(float a, float b)
clamp set data values in the range [a,b]
float * sort()
sort
Definition: image.hpp:871
Definition: io.hpp:27
int alpha
Definition: image.hpp:80
Definition: io.hpp:27
float * getMeanVal(BBox *box, float *ret)
getMeanVal computes the mean for the current Image.
void getNormalizedCoords(int x, int y, float &nx, float &ny)
getNormalizedCoords computes normalized coordinates (nx, ny) of (x, y).
Definition: image.hpp:638
PIC_INLINE unsigned char * ReadPGM(std::string nameFile, unsigned char *data, int &width, int &height, int &channels)
ReadPGM reads an .ppm file.
Definition: pgm.hpp:37
bool isSimilarType(const Image *img)
isSimilarType checks if the current image is similar to img; i.e. if they have the same width...
void scaleCosine()
scaleCosine multiplies the current image by the vertical cosine assuming a longitude-latitude image...
Definition: io.hpp:27
void minimum(Image *img)
minimum is the minimum operator for Image.
Definition: io.hpp:27
PIC_INLINE bool WriteHDR(std::string nameFile, float *data, int width, int height, int channels, float appliedExposure=1.0f, bool bRLE=true)
WriteHDR writes a .hdr/.pic file.
Definition: hdr.hpp:288
float channelsf
Definition: image.hpp:84
static T * mulS(T *bufferOut, T *bufferIn, int n, int channels)
mulS
Definition: buffer.hpp:204
bool flippedEXR
Definition: image.hpp:70
void setBox(int x0, int x1, int y0, int y1, int z0, int z1, int width, int height, int frames)
setBox sets a BBox up.
Definition: bbox.hpp:129
float * getSumVal(BBox *box, float *ret)
getSumVal sums values for the current Image.
const float C_PI
Definition: math.hpp:50
std::string nameFile
Definition: image.hpp:86
Image operator/(const float &a) const
operator /
Image operator-(const float &a) const
operator -
void allocateSimilarTo(Image *img)
allocateSimilarTo allocate an Image with similar size of the passed by.
float getDynamicRange(bool bRobust, float percentile)
getDynamicRange computes the dynamic range of the image.
PIC_INLINE bool isinf(T value)
isinf is it a Inf value?
Definition: math.hpp:103
int frames
Definition: image.hpp:80
float heightf
Definition: image.hpp:84
float framesf
Definition: image.hpp:84
bool getFlippedEXR()
getFlippedEXR returns the flippedEXR flag.
Definition: image.hpp:541
T * delete_vec_s(T *data)
delete_vec_s
Definition: std_util.hpp:138
float * getMedVal(BBox *box, float *ret)
getPercentileVal computes the median value value given a percentile.
PIC_INLINE unsigned char * ReadSTB(std::string nameFile, int &width, int &height, int &channels)
ReadSTB.
Definition: stb.hpp:57
LDR_type typeLoad
Definition: image.hpp:76
int getAddress(int x, int y, int t)
getAddress calculates a memory address from (x, y, t)
Definition: image.hpp:665
static void findSimple(T *data, int nData, bool(*func)(float), IntCoord &ret, int stride=1)
findSimple collects coordinates of data which satisfies a bool function func.
Definition: indexed_array.hpp:80
Definition: io.hpp:27
PIC_INLINE bool WriteEXR(std::string nameFile, float *data, int width, int height, int channels=3)
WriteEXR.
Definition: exr_tiny.hpp:95
LDR_type
The LDR_type enum.
Definition: dynamic_range.hpp:29
float * operator()(float x, float y)
operator () returns a pointer to a pixel at (x, y) with normalized coordinates (values in [0...
Definition: image.hpp:603
void flipV()
FlipV flips vertically the current image.
Definition: image.hpp:212
void maximum(Image *img)
maximum is the maximum operator for Image.
float * getMinVal(BBox *box, float *ret)
getMinVal computes the minimum value for the current Image.
static void rotate90CW(T *buffer, int &width, int &height, int channels)
rotate90CW rotates an image 90 CW
Definition: buffer.hpp:447
float * getLogMeanVal(BBox *box, float *ret)
getLogMeanVal computes the log mean for the current Image.
int getAddress(int x, int y)
getAddress calculates a memory address from (x, y)
Definition: image.hpp:650
static T * divS(T *bufferOut, T *bufferIn, int n, int channels)
divS
Definition: buffer.hpp:358
Definition: io.hpp:27
static void flipV(T *buffer, int width, int height, int channels, int frames)
flipV flips an image vertically
Definition: buffer.hpp:414
void operator-=(const float &a)
operator -=
static T * div(T *buffer, int n, T value)
div divides by a constant value
Definition: buffer.hpp:303
unsigned char * dataUC
dataUC is a buffer for rendering 8-bit images.
Definition: image.hpp:96
static bool bFuncNotNeg(T val)
bFuncNotNeg
Definition: indexed_array.hpp:48
bool notOwned
Definition: image.hpp:72
int Size()
Size computes the number of pixels in a bounding box.
Definition: bbox.hpp:112
static T min(T *data, IntCoord &coord)
min computes the min value.
Definition: indexed_array.hpp:136
Image operator*(const float &a) const
operator *
int nPixels() const
nPixels computes the number of pixels.
Definition: image.hpp:499
Definition: io.hpp:27
PIC_INLINE bool WriteVOL(std::string nameFile, float *data, int width, int height, int depth, int channels=3)
WriteVOL.
Definition: vol.hpp:119
float exposure
Definition: image.hpp:79
bool readEXIF(std::string name, EXIFInfo &info)
readEXIF
Definition: exif.hpp:250
PIC_INLINE bool isnan(T value)
isnan is it a NaN?
Definition: math.hpp:93
std::vector< int > IntCoord
IntCoord.
Definition: indexed_array.hpp:30
PIC_INLINE bool WritePGM(std::string nameFile, const unsigned char *data, int width, int height, int channels, bool bAscii=false)
WritePGM writes an .ppm file.
Definition: pgm.hpp:114
Definition: io.hpp:27
void blend(Image *img, Image *weight)
blend
bool * convertToMask(float *color, float threshold, bool cmp, bool *mask)
convertToMask converts an Image into a boolean mask.
Definition: io.hpp:27
BBox fullBox
Definition: image.hpp:74
void allocateAux()
allocateAux computes extra information after allocation; e.g. strides.
int xstride
Definition: image.hpp:82
float * getLL(float x, float y, float z)
getLL returns a pointer to a pixel given a normalized direction and assuming longituted-latitude mapp...
Definition: image.hpp:619
Image()
the basic construct of an Image
int depth
Definition: image.hpp:80
PIC_INLINE float * ReadEXR(std::string nameFile, float *data, int &width, int &height, int &channels)
Definition: exr_tiny.hpp:33
float height1f
Definition: image.hpp:84
#define PIC_INLINE
Definition: base.hpp:33
PIC_INLINE bool WritePFM(std::string nameFile, float *data, int width, int height, int channels=3)
WritePFM writes an HDR image in the portable float map format into a file.
Definition: pfm.hpp:148
void release()
release frees allocated buffers.
Definition: io.hpp:27
float widthf
Definition: image.hpp:84
void rotate90CW()
rotate90CW rotates 90 degrees clockwise the current image.
Definition: image.hpp:247
PIC_INLINE unsigned char * ReadBMP(std::string nameFile, unsigned char *data, int &width, int &height, int &channels)
ReadBMP reads an image as .bmp file.
Definition: bmp.hpp:94
static T getMin(T *data, int size, int &ind)
getMin
Definition: array.hpp:542
void applyFunction(float(*func)(float))
applyFunction is an operator that applies an input function to all values in data.
float * operator()(int x, int y)
operator () returns a pointer to a pixel at (x, y)
Definition: image.hpp:590
void applyFunctionParam(float(*func)(float, std::vector< float > &), std::vector< float > &param)
applyFunctionParam
PIC_INLINE bool WritePPM(std::string nameFile, const unsigned char *data, int width, int height, int channels)
WritePPM writes an .ppm file.
Definition: ppm.hpp:126
void setNULL()
setNULL sets buffers values to NULL.
PIC_INLINE LABEL_IO_EXTENSION getLabelHDRExtension(std::string nameFile)
getLabelHDRExtension returns the file label given its file name (for HDR images). ...
Definition: io.hpp:34
Definition: io.hpp:27
Definition: dynamic_range.hpp:29
The Image class stores an image as buffer of float.
Definition: image.hpp:60
PIC_INLINE unsigned char * ReadTGA(std::string nameFile, unsigned char *data, int &width, int &height, int &channels)
ReadTGA reads an image in the .tga format.
Definition: tga.hpp:62
static void div(T *data, int size, T value)
div
Definition: array.hpp:353
PIC_INLINE float * ReadPFM(std::string nameFile, float *data, int &width, int &height, int &channel)
ReadPFM loads a portable float map from a file.
Definition: pfm.hpp:59
Image * clone() const
Clone creates a deep copy of the calling instance.
void removeSpecials()
removeSpecials removes NaN and +/-Inf values and sets them to 0.0f.
PIC_INLINE bool WriteBMP(std::string nameFile, const unsigned char *data, int width, int height, int channels)
WriteBMP writes an image as a .bmp file.
Definition: bmp.hpp:188
float * getColorSamples(float *samples, int &nSamples, float percentage)
getColorSamples
Image * allocateSimilarOne()
allocateSimilarOne creates an Image with similar size of the calling instance.
int ystride
Definition: image.hpp:82
static T * subS(T *bufferOut, T *bufferIn, int n, int channels)
subS
Definition: buffer.hpp:280
Definition: dynamic_range.hpp:29
#define CLAMPi(x, a, b)
Definition: math.hpp:81
float * getPercentileVal(float percentile, BBox *box, float *ret)
getPercentileVal computes the n-th value given a percentile.
static void copySubBuffer(T *bufIn, int bi_width, int bi_height, int bi_channels, int startX, int startY, T *bufOut, int bo_width, int bo_height, int bo_channels)
copySubBuffer
Definition: buffer.hpp:746
Definition: dynamic_range.hpp:29
void operator=(const Image &a)
operator =
Definition: bilateral_separation.hpp:25
float getDiagonalSize()
getDiagonalSize
Definition: image.hpp:257
int tstride
Definition: image.hpp:82
PIC_INLINE float * ReadVOL(std::string nameFile, float *data, int &width, int &height, int &depth, int &channels)
ReadVOL.
Definition: vol.hpp:40
bool isValid()
isValid checks if the current image is valid, which means if they have an allocated buffer or not...
#define CLAMP(x, a)
Definition: math.hpp:77
LABEL_IO_EXTENSION
Definition: io.hpp:27
static T * assign(T *data, int size, T *ret)
assign
Definition: array.hpp:464
#define MAX(a, b)
Definition: math.hpp:73
void convertFromMask(bool *mask, int width, int height)
convertFromMask converts a boolean mask into an Image. true is mapped to 1.0f, and false is mapped to...
bool Read(std::string nameFile, LDR_type typeLoad)
Read opens an Image from a file on the disk.
void flipHV()
flipHV flips horizontally and vertically the current image.
Definition: image.hpp:220
static T * add(T *data, int size, T *ret)
add
Definition: array.hpp:334
static void flipH(T *buffer, int width, int height, int channels, int frames)
flipH flips a buffer horizontally
Definition: buffer.hpp:382
float * getMomentsVal(int x0, int y0, int radius, float *ret)
getMomentsVal computes the moments at pixel (x0, y0).
void copySubImage(Image *imgIn, int startX, int startY)
copySubImage copies imgIn in the current image. The current image is written from (startX...
PIC_INLINE bool WriteSTB(std::string nameFile, unsigned char *data, int width, int height, int channels=3)
WriteSTB.
Definition: stb.hpp:80
int sizeFrame() const
size computes the number of values.
Definition: image.hpp:490
PIC_INLINE bool WriteTGA(std::string nameFile, const unsigned char *data, int width, int height, int channels)
WriteTGA writes an image in the .tga format.
Definition: tga.hpp:139
PIC_INLINE LABEL_IO_EXTENSION getLabelLDRExtension(std::string nameFile)
getLabelHDRExtension returns the file label given its file name (for LDR images). ...
Definition: io.hpp:80
PIC_INLINE float * convertLDR2HDR(unsigned char *dataIn, float *dataOut, int size, LDR_type type, float gamma=2.2f)
convertLDR2HDR converts a buffer of unsigned char into float.
Definition: dynamic_range.hpp:78
void changeOwnership(bool notOwned)
changeOwnership
Definition: image.hpp:746
unsigned char * dataRGBE
dataRGBE is a buffer for rendering RGBE encoded images.
Definition: image.hpp:101
void setRand(unsigned int seed)
setRand
float * getMaxVal(BBox *box, float *ret)
getMaxVal computes the maximum value for the current Image.
PIC_INLINE float * ReadTMP(std::string nameFile, float *data, int &width, int &height, int &channels, int &frames, bool bHeader=true)
ReadTMP reads a dump temp file.
Definition: tmp.hpp:47
unsigned char * getdataUC()
getdataUC
Definition: image.hpp:464
static T * addS(T *bufferOut, T *bufferIn, int n, int channels)
Definition: buffer.hpp:125
PIC_INLINE float * ReadHDR(std::string nameFile, float *data, int &width, int &height)
ReadHDR reads a .hdr/.pic file.
Definition: hdr.hpp:38
int width
Definition: image.hpp:80
Definition: io.hpp:27
void rotate90CCW()
rotate90CCW rotates 90 degrees counter-clockwise the current image.
Definition: image.hpp:238
int height
Definition: image.hpp:80
void calculateStrides()
calculateStrides computes the strides values for pixels, lines and frames.
Definition: image.hpp:563
bool Write(std::string nameFile, LDR_type typeWrite, int writerCounter)
Write saves an Image into a file on the disk.
float * getVarianceVal(float *meanVal, BBox *box, float *ret)
getVarianceVal computes the variance for the current Image.
static T * BGRtoRGB(T *buffer, int width, int height, int channels, int frames)
BGRtoRGB swizzles from BGR to RGB a buffer.
Definition: buffer.hpp:659
PIC_INLINE unsigned char * convertHDR2LDR(const float *dataIn, unsigned char *dataOut, int size, LDR_type type, float gamma=2.2f)
convertHDR2LDR converts a buffer of float into unsigned char.
Definition: dynamic_range.hpp:132
void operator/=(const float &a)
operator /=
int readerCounter
Definition: image.hpp:71
static T * assign(T *buffer, int n, T value)
assign assigns value to buffer
Definition: buffer.hpp:45
const float C_INV_PI
Definition: math.hpp:62
void flipH()
FlipH flips horizontally the current image.
Definition: image.hpp:204
void operator+=(const float &a)
operator +=
PIC_INLINE unsigned char * ReadPPM(std::string nameFile, unsigned char *data, int &width, int &height, int &channels)
ReadPPM reads an .ppm file.
Definition: ppm.hpp:37
float frames1f
Definition: image.hpp:84
BBox getFullBox()
getFullBox computes a full BBox for this image.
PIC_INLINE float estimateAverageLuminance(float shutter_speed, float aperture_value=1.0f, float iso_value=1.0f, float K_value=12.5f)
estimateAverageLuminance estimates the average luminance of the shot.
Definition: dynamic_range.hpp:39
float width1f
Definition: image.hpp:84
bool checkCoordinates(int x, int y, int z=0)
checkCoordinates checks (x, y, z) coordinates) if they are valid or not.
Definition: image.hpp:512