Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PMDImageIO.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, Save to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include "PMDImageIO.hh"
26 #include <stdio.h>
27 #include <math.h>
28 #include <iostream>
29 
30 #define UINT16_MAX (65535U)
31 
32 // depth range in m
33 #define DEPTH_MAX 65.535f
34 #define DEPTH_MIN 0
35 // modulation coefficient range
36 #define MODCOEFF_MAX 1000
37 #define MODCOEFF_MIN 0
38 
39 using namespace std;
40 using namespace BIAS;
41 
42 // static
43 TIFFExtendProc PMDImageIO::ParentExtender = NULL;
44 
45 
46 // new tiff tag definitions for extrinsic and intrinsic camera parameters
47 static const TIFFFieldInfo tiffFieldInfo[] =
48  {{ TIFFTAG_PRINCIPALPOINT, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
49  (char*)("PrincipalPoint")},
50  { TIFFTAG_FOCALLENGTHX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
51  (char*)("FocalLengthX") },
52  { TIFFTAG_ASPECTRATIO, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
53  (char*)("AspectRatio") },
54  { TIFFTAG_UNDISTORTION, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
55  (char*)("BougetUndistortion") },
56  { TIFFTAG_CAMERACENTER, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
57  (char*)("CameraCenter") },
58  { TIFFTAG_CAMERAROTATION, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true,
59  (char*)("CameraRotation") }
60 };
61 
62 
63 #ifndef BIASERR
64 
65 #ifdef WIN32
66 # define FUNCNAME __FUNCTION__
67 #else // WIN32
68 # define FUNCNAME __PRETTY_FUNCTION__
69 #endif // WIN32
70 
71 # define BIASERR(arg) { \
72  cerr<<std::flush<<"Error in "<<__FILE__<<":"<<__LINE__<<" : "<<FUNCNAME<<std::endl \
73  <<"\t"<<arg<<std::endl<<std::flush; \
74 }
75 
76 #endif
77 
78 int PMDImageIO::Save2DImage8Bit_(TIFF *tiffimage, uint8* Img2D,
79  PMDImageMetaData MetaData2D,
80  int LinesPerStrip) {
81 
82  TIFFSetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, "2D-Image");
83  // We need to set some values for basic tags before we can add any data
84  TIFFSetField(tiffimage, TIFFTAG_IMAGEWIDTH, MetaData2D.width);
85  TIFFSetField(tiffimage, TIFFTAG_IMAGELENGTH, MetaData2D.height);
86  TIFFSetField(tiffimage, TIFFTAG_BITSPERSAMPLE, 8);
87  TIFFSetField(tiffimage, TIFFTAG_SAMPLESPERPIXEL, MetaData2D.channels);
88  TIFFSetField(tiffimage, TIFFTAG_ROWSPERSTRIP, LinesPerStrip);
89  //TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
90  TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
91  if (MetaData2D.channels==3) {
92  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
93  } else {
94  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
95  }
96  //TIFFSetField(tiffimage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
97  TIFFSetField(tiffimage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
98 
99  SaveMetaData_(tiffimage, MetaData2D);
100 
101  // Save the information to the file
102  unsigned char* ipt = Img2D;
103 
104  for (unsigned int i=0;
105  i< ceil((double)MetaData2D.height/(double)LinesPerStrip); i++) {
106  int bytecount = MetaData2D.width*LinesPerStrip*MetaData2D.channels;
107  if ((i+1)*LinesPerStrip>MetaData2D.height) {
108  bytecount = (MetaData2D.height-i*LinesPerStrip)*
109  MetaData2D.width*MetaData2D.channels;
110  }
111  TIFFReadEncodedStrip(tiffimage, i, ipt, bytecount);
112  ipt+=MetaData2D.width*LinesPerStrip*MetaData2D.channels;
113  }
114  return 0;
115 }
116 
117 
118 int PMDImageIO::Save2DImage16Bit_(TIFF *tiffimage, uint16* Img2D,
119  PMDImageMetaData MetaData2D,
120  int LinesPerStrip) {
121 
122  TIFFSetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, "2D-Image");
123  // We need to set some values for basic tags before we can add any data
124  TIFFSetField(tiffimage, TIFFTAG_IMAGEWIDTH, MetaData2D.width);
125  TIFFSetField(tiffimage, TIFFTAG_IMAGELENGTH, MetaData2D.height);
126  TIFFSetField(tiffimage, TIFFTAG_BITSPERSAMPLE, 16);
127  TIFFSetField(tiffimage, TIFFTAG_SAMPLESPERPIXEL, MetaData2D.channels);
128  TIFFSetField(tiffimage, TIFFTAG_ROWSPERSTRIP, LinesPerStrip);
129  //TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
130  TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
131  if (MetaData2D.channels==3) {
132  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
133  } else {
134  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
135  }
136  //TIFFSetField(tiffimage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
137  TIFFSetField(tiffimage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
138 
139  SaveMetaData_(tiffimage, MetaData2D);
140 
141  // Save the information to the file
142  unsigned char* ipt = (unsigned char*) Img2D;
143 
144  for (unsigned int i=0;
145  i< ceil((double)MetaData2D.height/(double)LinesPerStrip); i++) {
146  int bytecount = MetaData2D.width*LinesPerStrip*MetaData2D.channels*2;
147  if ((i+1)*LinesPerStrip>MetaData2D.height) {
148  bytecount = (MetaData2D.height-i*LinesPerStrip)*
149  MetaData2D.width*MetaData2D.channels*2;
150  }
151  TIFFWriteEncodedStrip(tiffimage, i, ipt, bytecount);
152  ipt+=MetaData2D.width*LinesPerStrip*MetaData2D.channels*2;
153  }
154  return 0;
155 }
156 
157 
158 int PMDImageIO::SaveDepthImage_(TIFF *tiffimage, uint16* ImgDepth,
159  PMDImageMetaData MetaDataDepth,
160  int LinesPerStrip) {
161 
162  TIFFSetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, "Depth-Image");
163  // We need to set some values for basic tags before we can add any data
164  TIFFSetField(tiffimage, TIFFTAG_IMAGEWIDTH, MetaDataDepth.width);
165  TIFFSetField(tiffimage, TIFFTAG_IMAGELENGTH, MetaDataDepth.height);
166  TIFFSetField(tiffimage, TIFFTAG_BITSPERSAMPLE, 16);
167  TIFFSetField(tiffimage, TIFFTAG_SAMPLESPERPIXEL, 1);
168  TIFFSetField(tiffimage, TIFFTAG_ROWSPERSTRIP, LinesPerStrip);
169  //TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
170  TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
171  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
172  //TIFFSetField(tiffimage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
173  TIFFSetField(tiffimage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
174 
175  SaveMetaData_(tiffimage, MetaDataDepth);
176 
177  // Save the information to the file
178  unsigned char* ipt = (unsigned char*) ImgDepth;
179  for (unsigned int i=0;
180  i< ceil((double)MetaDataDepth.height/(double)LinesPerStrip); i++) {
181  int bytecount = MetaDataDepth.width*LinesPerStrip*
182  MetaDataDepth.channels*2;
183  if ((i+1)*LinesPerStrip>MetaDataDepth.height) {
184  bytecount = (MetaDataDepth.height-i*LinesPerStrip)*
185  MetaDataDepth.width*MetaDataDepth.channels*2;
186  }
187  TIFFWriteEncodedStrip(tiffimage, i, ipt, bytecount);
188  ipt+=MetaDataDepth.width*LinesPerStrip*
189  MetaDataDepth.channels*2;
190  }
191  return 0;
192 }
193 
194 
195 int PMDImageIO::SaveModCoeffImage_(TIFF *tiffimage, uint16* ImgModCoeff,
196  PMDImageMetaData MetaDataDepth,
197  int LinesPerStrip) {
198 
199  TIFFSetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION,
200  "Modulation-Coefficients");
201  // We need to set some values for basic tags before we can add any data
202  TIFFSetField(tiffimage, TIFFTAG_IMAGEWIDTH, MetaDataDepth.width);
203  TIFFSetField(tiffimage, TIFFTAG_IMAGELENGTH, MetaDataDepth.height);
204  TIFFSetField(tiffimage, TIFFTAG_BITSPERSAMPLE, 16);
205  TIFFSetField(tiffimage, TIFFTAG_SAMPLESPERPIXEL, 1);
206  TIFFSetField(tiffimage, TIFFTAG_ROWSPERSTRIP, LinesPerStrip);
207  //TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
208  TIFFSetField(tiffimage, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
209  TIFFSetField(tiffimage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
210  //TIFFSetField(tiffimage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
211  TIFFSetField(tiffimage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
212 
213  // The metadata of the modulatioin coefficient is the same as for
214  // the depth image
215  SaveMetaData_(tiffimage, MetaDataDepth);
216 
217  // Save the information to the file
218  unsigned char* ipt = (unsigned char*) ImgModCoeff;
219  for (unsigned int i=0;
220  i< ceil((double)MetaDataDepth.height/(double)LinesPerStrip); i++) {
221  int bytecount = MetaDataDepth.width*LinesPerStrip*
222  MetaDataDepth.channels*2;
223  if ((i+1)*LinesPerStrip>MetaDataDepth.height) {
224  bytecount = (MetaDataDepth.height-i*LinesPerStrip)*
225  MetaDataDepth.width*MetaDataDepth.channels*2;
226  }
227  TIFFWriteEncodedStrip(tiffimage, i, ipt, bytecount);
228  ipt+=MetaDataDepth.width*LinesPerStrip*
229  MetaDataDepth.channels*2;
230  }
231  return 0;
232 }
233 
234 
235 int PMDImageIO::Save(const std::string& FileName,
236  uint8* Img2D, uint16* ImgDepth,
237  uint16* ImgModCoeff,
238  const PMDImageMetaData &MetaData2D,
239  const PMDImageMetaData &MetaDataDepth) {
240 
241  // Open the TIFF file
242  TIFF *tiffimage;
243  int LinesPerStrip=10;
244 
245  /* Set up the callback */
246  NewTagsInitialize_();
247 
248  if((tiffimage = TIFFOpen(FileName.c_str(), "w")) == NULL){
249  BIASERR("Could not open image for writing:" << FileName);
250  return -1;
251  }
252 
253  // Save the rgb or grey image
254  if (Img2D!=NULL) {
255  Save2DImage8Bit_(tiffimage, Img2D, MetaData2D, LinesPerStrip);
256  }
257 
258  // Save the depth image
259  if (ImgDepth!=NULL) {
260  if (Img2D!=NULL) TIFFWriteDirectory(tiffimage);
261  SaveDepthImage_(tiffimage, ImgDepth, MetaDataDepth, LinesPerStrip);
262  }
263 
264  // Save the modulation coefficients
265  // No modulation coefficients without a depth image
266  if (ImgDepth!=NULL && ImgModCoeff!=NULL) {
267 
268  TIFFWriteDirectory(tiffimage);
269  SaveModCoeffImage_(tiffimage, ImgModCoeff, MetaDataDepth, LinesPerStrip);
270  }
271 
272  // Close the file
273  TIFFClose(tiffimage);
274  return 0;
275 }
276 
277 
278 int PMDImageIO::Save(const std::string& FileName,
279  uint16* Img2D, uint16* ImgDepth,
280  uint16* ImgModCoeff,
281  const PMDImageMetaData &MetaData2D,
282  const PMDImageMetaData &MetaDataDepth) {
283 
284  // Open the TIFF file
285  TIFF *tiffimage;
286  int LinesPerStrip=10;
287 
288  /* Set up the callback */
289  NewTagsInitialize_();
290 
291  if((tiffimage = TIFFOpen(FileName.c_str(), "w")) == NULL){
292  BIASERR("Could not open image for writing:" << FileName);
293  return -1;
294  }
295 
296  // Save the rgb or grey image
297  if (Img2D!=NULL) {
298  Save2DImage16Bit_(tiffimage, Img2D, MetaData2D, LinesPerStrip);
299  }
300 
301  // Save the depth image
302  if (ImgDepth!=NULL) {
303  if (Img2D!=NULL) TIFFWriteDirectory(tiffimage);
304  SaveDepthImage_(tiffimage, ImgDepth, MetaDataDepth, LinesPerStrip);
305  }
306 
307  // Save the modulation coefficients
308  // No modulation coefficients without a depth image
309  if (ImgDepth!=NULL && ImgModCoeff!=NULL) {
310 
311  TIFFWriteDirectory(tiffimage);
312  SaveModCoeffImage_(tiffimage, ImgModCoeff, MetaDataDepth, LinesPerStrip);
313  }
314 
315  // Close the file
316  TIFFClose(tiffimage);
317  return 0;
318 }
319 
320 
321 // Load the rgb or grey image -----------------
322 int PMDImageIO::Load2DImage8Bit_(TIFF *tiffimage,
323  uint8* &Img2D,
324  PMDImageMetaData &MetaData2D) {
325 
326  uint16 bps, photo;
327 
328  if((TIFFGetField(tiffimage, TIFFTAG_BITSPERSAMPLE, &bps) == 0) ||
329  (bps != 8)){
330  BIASERR("Bits per Sample != 8!");
331  return -1;
332  }
333 
334  if(TIFFGetField(tiffimage, TIFFTAG_PHOTOMETRIC, &photo) == 0 ||
335  (photo != PHOTOMETRIC_RGB && photo != PHOTOMETRIC_MINISBLACK)){
336  BIASERR("Image has the wrong photometric interpretation! Trying PHOTOMETRIC_MINISBLACK.");
337  photo = PHOTOMETRIC_MINISBLACK;
338  // return -1;
339  }
340 
341  LoadMetaData_(tiffimage, MetaData2D);
342 
343  if ((MetaData2D.channels!=3) && (MetaData2D.channels!=1)) {
344  BIASERR("Wrong number of channels in 2D image!");
345  return -1;
346  }
347 
348  // Load in the possibly multiple strips
349  tsize_t stripSize = TIFFStripSize (tiffimage);
350  int stripMax = TIFFNumberOfStrips (tiffimage);
351 
352  unsigned char *ipt = new unsigned char[MetaData2D.height*
353  MetaData2D.width*
354  MetaData2D.channels];
355  Img2D = ipt;
356 
357  for (int i = 0; i < stripMax; i++){
358  if (i==stripMax-1) {
359  stripSize = MetaData2D.height*MetaData2D.width*
360  MetaData2D.channels-i*stripSize;
361  }
362  if(TIFFReadEncodedStrip(tiffimage, i, ipt, stripSize)<0){
363  BIASERR("Load error on input strip number "<< i);
364  return -1;
365  }
366  ipt += stripSize;
367  }
368  return 0;
369 }
370 
371 
372  // Load the rgb or grey image -----------------
373 int PMDImageIO::Load2DImage16Bit_(TIFF *tiffimage,
374  uint16* &Img2D,
375  PMDImageMetaData &MetaData2D){
376 
377  uint16 bps, photo;
378 
379  if((TIFFGetField(tiffimage, TIFFTAG_BITSPERSAMPLE, &bps) == 0) ||
380  (bps != 16)){
381  BIASERR("Bits per Sample != 16!");
382  return -1;
383  }
384 
385  if(TIFFGetField(tiffimage, TIFFTAG_PHOTOMETRIC, &photo) == 0 ||
386  (photo != PHOTOMETRIC_RGB && photo != PHOTOMETRIC_MINISBLACK)){
387  BIASERR("Image has the wrong photometric interpretation!");
388  return -1;
389  }
390 
391  LoadMetaData_(tiffimage, MetaData2D);
392 
393  if ((MetaData2D.channels!=3) && (MetaData2D.channels!=1)) {
394  BIASERR("Wrong number of channels in 2D image!");
395  return -1;
396  }
397 
398  // Load in the possibly multiple strips
399  tsize_t stripSize = TIFFStripSize (tiffimage);
400  int stripMax = TIFFNumberOfStrips (tiffimage);
401 
402  unsigned char *ipt = new unsigned char[MetaData2D.height*
403  MetaData2D.width*
404  MetaData2D.channels*2];
405  Img2D = (uint16*)ipt;
406 
407  for (int i = 0; i < stripMax; i++){
408  if (i==stripMax-1) {
409  stripSize = MetaData2D.height*MetaData2D.width*
410  MetaData2D.channels-i*stripSize;
411  }
412  if(TIFFReadEncodedStrip(tiffimage, i, ipt, stripSize)<0){
413  BIASERR("Load error on input strip number "<< i);
414  return -1;
415  }
416  ipt += stripSize;
417  }
418  return 0;
419 }
420 
421 // Load the depth-image
422 int PMDImageIO::LoadDepthImage_(TIFF *tiffimage,
423  uint16* &ImgDepth,
424  PMDImageMetaData &MetaDataDepth) {
425 
426  uint16 dbps, dphoto;
427 
428  if((TIFFGetField(tiffimage, TIFFTAG_BITSPERSAMPLE, &dbps) == 0) ||
429  (dbps != 16)){
430  BIASERR("Bits per Sample != 16!");
431  return -1;
432  }
433 
434  if(TIFFGetField(tiffimage, TIFFTAG_PHOTOMETRIC, &dphoto) == 0 ||
435  (dphoto != PHOTOMETRIC_MINISBLACK)){
436  BIASERR("Depth Image has the wrong photometric interpretation!");
437  return -1;
438  }
439 
440  LoadMetaData_(tiffimage, MetaDataDepth);
441 
442  if (MetaDataDepth.channels!=1) {
443  BIASERR("Wrong number of channels in Depth image!");
444  return -1;
445  }
446 
447  // Load in the possibly multiple strips
448  tsize_t stripSize = TIFFStripSize (tiffimage);
449  int stripMax = TIFFNumberOfStrips (tiffimage);
450 
451  unsigned char* ipt = new unsigned char[MetaDataDepth.height*
452  MetaDataDepth.width*
453  MetaDataDepth.channels*2];
454  ImgDepth = (uint16*)ipt;
455  for (int i = 0; i < stripMax; i++){
456  if (i==stripMax-1) {
457  stripSize = MetaDataDepth.height*MetaDataDepth.width*
458  MetaDataDepth.channels*2-i*stripSize;
459  }
460  if(TIFFReadEncodedStrip(tiffimage, i, ipt, stripSize)<0){
461  BIASERR("Load error on input strip number "<< i);
462  return -1;
463  }
464  ipt += stripSize;
465  }
466  return 0;
467 }
468 
469 // Load the Modulation-Coefficients
470 int PMDImageIO::LoadModCoeffImage_(TIFF *tiffimage,
471  uint16* &ImgModCoeff,
472  PMDImageMetaData MetaDataDepth) {
473 
474  uint16 dbps, dphoto;
475 
476  if((TIFFGetField(tiffimage, TIFFTAG_BITSPERSAMPLE, &dbps) == 0) ||
477  (dbps != 16)){
478  BIASERR("Bits per Sample != 16!");
479  return -1;
480  }
481 
482  if(TIFFGetField(tiffimage, TIFFTAG_PHOTOMETRIC, &dphoto) == 0 ||
483  (dphoto != PHOTOMETRIC_MINISBLACK)){
484  BIASERR("Modulation Coefficients have the wrong photometric"
485  << "interpretation!");
486  return -1;
487  }
488 
489  LoadMetaData_(tiffimage, MetaDataDepth);
490 
491  if (MetaDataDepth.channels!=1) {
492  BIASERR("Wrong number of channels in Modulation Coefficients image!");
493  return -1;
494  }
495 
496  // Load in the possibly multiple strips
497  tsize_t stripSize = TIFFStripSize (tiffimage);
498  int stripMax = TIFFNumberOfStrips (tiffimage);
499 
500  unsigned char* ipt = new unsigned char[MetaDataDepth.height*
501  MetaDataDepth.width*
502  MetaDataDepth.channels*2];
503  ImgModCoeff = (uint16*)ipt;
504  for (int i = 0; i < stripMax; i++){
505  if (i==stripMax-1) {
506  stripSize = MetaDataDepth.height*MetaDataDepth.width*
507  MetaDataDepth.channels*2-i*stripSize;
508  }
509  if(TIFFReadEncodedStrip(tiffimage, i, ipt, stripSize)<0){
510  BIASERR("Load error on input strip number "<< i);
511  return -1;
512  }
513  ipt += stripSize;
514  }
515  return 0;
516 }
517 
518 
519 int PMDImageIO::Load(const std::string& FileName,
520  uint16* &Img2D, uint16* &ImgDepth,
521  uint16* &ImgModCoeff,
522  PMDImageMetaData &MetaData2D,
523  PMDImageMetaData &MetaDataDepth){
524  // reset image pointer
525  Img2D=NULL;
526  ImgDepth=NULL;
527  ImgModCoeff=NULL;
528 
529  // Open the TIFF file
530  TIFF *tiffimage;
531 
532  /* Set up the callback */
533  NewTagsInitialize_();
534 
535  if((tiffimage = TIFFOpen(FileName.c_str(), "r")) == NULL){
536  BIASERR("Could not open image for Loading:" << FileName);
537  return -1;
538  }
539 
540  do {
541  char* descr;
542  if (TIFFGetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, &descr) == 0) {
543  BIASERR("Image description is missing!");
544  return -1;
545  }
546 
547  if(strcmp(descr, "2D-Image") == 0) {
548  if (Load2DImage16Bit_(tiffimage, Img2D, MetaData2D)<0)
549  return -1;
550  }
551 
552  if(strcmp(descr, "Depth-Image") == 0) {
553  if (LoadDepthImage_(tiffimage, ImgDepth, MetaDataDepth)<0)
554  return -2;
555  }
556 
557  if(strcmp(descr, "Modulation-Coefficients") == 0) {
558  if (LoadModCoeffImage_(tiffimage, ImgModCoeff, MetaDataDepth)<0)
559  return -3;
560  }
561 
562  } while (TIFFReadDirectory(tiffimage)!=0);
563 
564  // Close the file
565  TIFFClose(tiffimage);
566  return 0;
567 }
568 
569 
570 int PMDImageIO::Load(const std::string& FileName,
571  uint8* &Img2D, uint16* &ImgDepth,
572  uint16* &ImgModCoeff,
573  PMDImageMetaData &MetaData2D,
574  PMDImageMetaData &MetaDataDepth){
575 
576  // reset image pointer
577  Img2D=NULL;
578  ImgDepth=NULL;
579  ImgModCoeff=NULL;
580 
581  // Open the TIFF file
582  TIFF *tiffimage;
583 
584  /* Set up the callback */
585  NewTagsInitialize_();
586 
587  if((tiffimage = TIFFOpen(FileName.c_str(), "r")) == NULL){
588  BIASERR("Could not open image for Loading:" << FileName);
589  return -1;
590  }
591 
592  do {
593  char* descr;
594  if (TIFFGetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, &descr) == 0) {
595  BIASERR("Image description is missing!");
596  return -1;
597  }
598 
599  if(strcmp(descr, "2D-Image") == 0) {
600  if (Load2DImage8Bit_(tiffimage, Img2D, MetaData2D)<0)
601  return -1;
602  }
603 
604  if(strcmp(descr, "Depth-Image") == 0) {
605  if (LoadDepthImage_(tiffimage, ImgDepth, MetaDataDepth)<0)
606  return -2;
607  }
608 
609  if(strcmp(descr, "Modulation-Coefficients") == 0) {
610  if (LoadModCoeffImage_(tiffimage, ImgModCoeff, MetaDataDepth)<0)
611  return -3;
612  }
613 
614  } while (TIFFReadDirectory(tiffimage)!=0);
615 
616  // Close the file
617  TIFFClose(tiffimage);
618  return 0;
619 }
620 
621 
622 #ifdef BIAS_HAVE_XML2
623 
624 int PMDImageIO::LoadXML(const std::string& FileName,
625  uint16* &Img2D, uint16* &ImgDepth,
626  uint16* &ImgModCoeff,
627  PMDImageMetaData &MetaData2D,
628  PMDImageMetaData &MetaDataDepth){
629 
630  // Open the XML file
631  XMLIO myXML;
632  xmlNodePtr rootNode;
633  rootNode = myXML.read(FileName);
634  if (rootNode==NULL) {
635  BIASERR("PMD-XML-File not found or parse error: " << FileName);
636  return -1;
637  }
638  if (myXML.getNodeName(rootNode)!="frame" && myXML.getNodeName(rootNode)!="sequence") {
639  BIASERR("Root node has to be \"frame\" or \"sequence\"");
640  return -1;
641  }
642  if (myXML.getNodeName(rootNode)=="sequence") {
643  rootNode = myXML.getChild(rootNode, "frame");
644  if (rootNode==NULL) {
645  BIASERR("Root node \"sequence\" has no child \"frame\"");
646  return -1;
647  }
648  }
649  return LoadXML(myXML, rootNode, Img2D, ImgDepth, ImgModCoeff, MetaData2D, MetaDataDepth);
650 
651 }
652 
653 int PMDImageIO::LoadXML(XMLIO &myXML, xmlNodePtr &rootNode,
654  uint16* &Img2D, uint16* &ImgDepth,
655  uint16* &ImgModCoeff,
656  PMDImageMetaData &MetaData2D,
657  PMDImageMetaData &MetaDataDepth){
658  // reset image pointer
659  Img2D=NULL;
660  ImgDepth=NULL;
661  ImgModCoeff=NULL;
662 
663  unsigned int width, height;
664  double aspectratio;
665 
666  width = myXML.getAttributeValueInt(rootNode, "width");
667  height = myXML.getAttributeValueInt(rootNode, "height");
668  aspectratio = myXML.getAttributeValueDouble(rootNode, "aspect");
669 
670  xmlNodePtr childNode;
671  vector<int> content;
672  childNode = myXML.getChild(rootNode, "grayscale");
673  if (childNode!=NULL) {
674  Img2D = new uint16[width*height];
675  uint16* pI = Img2D;
676  content = myXML.getNodeContentVectorInt(childNode);
677  if (content.size()!=width*height) {
678  BIASERR("Error in XML-File!!");
679  return -1;
680  }
681  for (unsigned int i=0; i<content.size(); i++) {
682  *pI = (uint16)content[i];
683  pI++;
684  }
685  }
686 
687  childNode = myXML.getChild(rootNode, "distance");
688  if (childNode!=NULL) {
689  ImgDepth = new uint16[width*height];
690  uint16* pI = ImgDepth;
691  content = myXML.getNodeContentVectorInt(childNode);
692  if (content.size()!=width*height) {
693  BIASERR("Error in XML-File!!");
694  return -1;
695  }
696  for (unsigned int i=0; i<content.size(); i++) {
697  *pI = (uint16)content[i];
698  pI++;
699  }
700  }
701 
702  childNode = myXML.getChild(rootNode, "amplitude");
703  if (childNode!=NULL) {
704  ImgModCoeff = new uint16[width*height];
705  uint16* pI = ImgModCoeff;
706  content = myXML.getNodeContentVectorInt(childNode);
707  if (content.size()!=width*height) {
708  BIASERR("Error in XML-File!!");
709  return -1;
710  }
711  for (unsigned int i=0; i<content.size(); i++) {
712  *pI = (uint16)content[i];
713  pI++;
714  }
715  }
716 
717  MetaData2D.width = MetaDataDepth.width = width;
718  MetaData2D.height = MetaDataDepth.height = height;
719  MetaData2D.channels = MetaDataDepth.channels = 1;
720  MetaData2D.PrincipalX = MetaDataDepth.PrincipalX = (double)width/2.0;
721  MetaData2D.PrincipalY = MetaDataDepth.PrincipalY = (double)height/2.0;
722  MetaData2D.FocallengthX = MetaDataDepth.FocallengthX = 1;
723  MetaData2D.AspectRatio = MetaDataDepth.AspectRatio = 1/(aspectratio/((double)width/(double)height));
724  MetaData2D.UndistCoeff[0] = MetaDataDepth.UndistCoeff[0] = 0;
725  MetaData2D.UndistCoeff[1] = MetaDataDepth.UndistCoeff[1] = 0;
726  MetaData2D.UndistCoeff[2] = MetaDataDepth.UndistCoeff[2] = 0;
727  MetaData2D.UndistCoeff[3] = MetaDataDepth.UndistCoeff[3] = 0;
728  MetaData2D.CameraCenter[0] = MetaDataDepth.CameraCenter[0] = 0;
729  MetaData2D.CameraCenter[1] = MetaDataDepth.CameraCenter[1] = 0;
730  MetaData2D.CameraCenter[2] = MetaDataDepth.CameraCenter[2] = 0;
731  MetaData2D.CameraRotation[0] = MetaDataDepth.CameraRotation[0] = 0;
732  MetaData2D.CameraRotation[1] = MetaDataDepth.CameraRotation[1] = 0;
733  MetaData2D.CameraRotation[2] = MetaDataDepth.CameraRotation[2] = 0;
734 
735  return 0;
736 }
737 
738 
739 
740 #endif // BIAS_HAVE_XML2
741 
742 
743 int PMDImageIO::Save(const std::string& FileName,
744  Image<unsigned char> &Img2D,
745  Image<float> &ImgDepth,
746  Image<float> &ImgModCoeff,
747  PMDImageMetaData &MetaData2D,
748  PMDImageMetaData &MetaDataDepth) {
749 
750  uint8* data2D=NULL;
751  uint16* dataDepth=NULL;
752  uint16* dataModCoeff=NULL;
753 
754  if (Img2D.IsEmpty()) {
755  BIASERR("2D-Data is necessary!");
756  return -1;
757  }
758 
759  MetaData2D.width = Img2D.GetWidth();
760  MetaData2D.height = Img2D.GetHeight();
761  MetaData2D.channels = Img2D.GetChannelCount();
762 
763  if (Img2D.GetStorageType()!=ImageBase::ST_unsignedchar) {
764  BIASERR("The RGB or grey image has the wrong storage type, has to be" <<
765  "ST_unsignedchar");
766  return -1;
767  }
768 
769  data2D = (uint8*) Img2D.GetImageData();
770 
771  if (!ImgDepth.IsEmpty()) {
772 
773  MetaDataDepth.width = ImgDepth.GetWidth();
774  MetaDataDepth.height = ImgDepth.GetHeight();
775  MetaDataDepth.channels = ImgDepth.GetChannelCount();
776  if (ImgDepth.GetStorageType()!=ImageBase::ST_float) {
777  BIASERR("The depth image has the wrong storage type, has to be" <<
778  "ST_float");
779  return -1;
780  }
781 
782  unsigned int i;
783  dataDepth = new uint16[MetaDataDepth.width*MetaDataDepth.height];
784  uint16* pDataDepth = dataDepth;
785  float* pDataDepthf = ImgDepth.GetImageData();
786  for (i=0; i<MetaDataDepth.width*MetaDataDepth.height;
787  i++, pDataDepthf++, pDataDepth++) {
788  *pDataDepth =DepthConvert_(*pDataDepthf);
789  }
790 
791  if (!ImgModCoeff.IsEmpty()) {
792  if (ImgModCoeff.GetStorageType()!=ImageBase::ST_float) {
793  BIASERR("The modulation coefficients image has the wrong storage" <<
794  "type, has to be ST_float");
795  return -1;
796  }
797  if (MetaDataDepth.width != ImgModCoeff.GetWidth() ||
798  MetaDataDepth.height != ImgModCoeff.GetHeight() ||
799  MetaDataDepth.channels != ImgModCoeff.GetChannelCount()) {
800  BIASERR("The modulation coefficients image must have same size " <<
801  "and channels as the depth image");
802  return -1;
803  }
804 
805  dataModCoeff = new uint16[MetaDataDepth.width*MetaDataDepth.height];
806  uint16* pDataModCoeff = dataModCoeff;
807  float* pDataModCoefff = ImgModCoeff.GetImageData();
808  for (i=0; i<MetaDataDepth.width*MetaDataDepth.height;
809  i++, pDataModCoefff++, pDataModCoeff++) {
810  *pDataModCoeff = ModCoeffConvert_(*pDataModCoefff);
811  }
812  }
813  }
814  PMDImageIO::Save(FileName, data2D, dataDepth, dataModCoeff,
815  MetaData2D, MetaDataDepth);
816 
817  if (dataDepth!=NULL) delete [] dataDepth;
818  if (dataModCoeff!=NULL) delete [] dataModCoeff;
819 
820  return 0;
821 
822 }
823 
824 
825 int PMDImageIO::Load(const std::string& FileName,
826  Image<unsigned char> &Img2D,
827  Image<float> &ImgDepth,
828  Image<float> &ImgModCoeff,
829  PMDImageMetaData &MetaData2D,
830  PMDImageMetaData &MetaDataDepth) {
831 
832 #ifdef BIAS_HAVE_XML2
833  if (strstr(FileName.c_str(),".xml")!=NULL) {
834  return PMDImageIO::LoadFromXML(FileName, Img2D, ImgDepth, ImgModCoeff,
835  MetaData2D, MetaDataDepth);
836  } else {
837 #endif
838  return PMDImageIO::LoadFromTIFF(FileName, Img2D, ImgDepth, ImgModCoeff,
839  MetaData2D, MetaDataDepth);
840 #ifdef BIAS_HAVE_XML2
841  }
842 #endif
843 
844 }
845 
846 
847 #ifdef BIAS_HAVE_XML2
848 
849 int PMDImageIO::LoadFromXML(const std::string& FileName,
850  Image<unsigned char> &Img2D,
851  Image<float> &ImgDepth,
852  Image<float> &ImgModCoeff,
853  PMDImageMetaData &MetaData2D,
854  PMDImageMetaData &MetaDataDepth) {
855 
856  uint8* data2d=NULL;
857  uint16* data2d16=NULL;
858  uint16* dataDepth=NULL;
859  uint16* dataModCoeff=NULL;
860 
861  if (PMDImageIO::LoadXML(FileName, data2d16, dataDepth, dataModCoeff,
862  MetaData2D, MetaDataDepth)<0) {
863  BIASERR("Could not Load XML-image.");
864  return -1;
865  } else {
866  Grey16to8Bit_(data2d16, data2d,
867  MetaData2D.width*MetaData2D.height*MetaData2D.channels);
868  return PostprocessData_(data2d, dataDepth, dataModCoeff,
869  Img2D, ImgDepth, ImgModCoeff,
870  MetaData2D, MetaDataDepth);
871  }
872 }
873 
874 
875 int PMDImageIO::LoadFromXML(const std::string& FileName,
876  vector<Image<unsigned char> > &vecImg2D,
877  vector<Image<float> > &vecImgDepth,
878  vector<Image<float> > &vecImgModCoeff,
879  vector<PMDImageMetaData> &vecMetaData2D,
880  vector<PMDImageMetaData> &vecMetaDataDepth)
881 {
882 
883  uint8* data2d=NULL;
884  uint16* data2d16=NULL;
885  uint16* dataDepth=NULL;
886  uint16* dataModCoeff=NULL;
887 
888  Image<unsigned char> Img2D;
889  Image<float> ImgDepth;
890  Image<float> ImgModCoeff;
891  PMDImageMetaData MetaData2D;
892  PMDImageMetaData MetaDataDepth;
893 
894  // Open the XML file
895  XMLIO myXML;
896  xmlNodePtr rootNode, childNode, tempChildNode;
897  rootNode = myXML.read(FileName);
898  if (rootNode==NULL) {
899  BIASERR("PMD-XML-File not found or parse error: " << FileName);
900  return -1;
901  }
902  if (myXML.getNodeName(rootNode)=="sequence") {
903  childNode = myXML.getFirstChild(rootNode);
904  while (childNode!=NULL) {
905  if (myXML.getNodeName(childNode)=="frame") {
906  tempChildNode = childNode;
907  if (PMDImageIO::LoadXML(myXML, tempChildNode, data2d16, dataDepth, dataModCoeff,
908  MetaData2D, MetaDataDepth)<0)
909  {
910  BIASERR("Could not Load XML-image.");
911  return -1;
912  } else {
913  Grey16to8Bit_(data2d16, data2d,
914  MetaData2D.width*MetaData2D.height*MetaData2D.channels);
915  if (PostprocessData_(data2d, dataDepth, dataModCoeff,
916  Img2D, ImgDepth, ImgModCoeff,
917  MetaData2D, MetaDataDepth)<0)
918  {
919  BIASERR("Error writing images to BIAS::Image.");
920  return -1;
921  }
922  vecImg2D.push_back(Img2D);
923  vecImgDepth.push_back(ImgDepth);
924  vecImgModCoeff.push_back(ImgModCoeff);
925  vecMetaData2D.push_back(MetaData2D);
926  vecMetaDataDepth.push_back(MetaDataDepth);
927  }
928  }
929  childNode = myXML.getNextChild(childNode);
930  }
931  } else {
932  if (myXML.getNodeName(rootNode)=="frame") {
933  if (LoadFromXML(FileName, Img2D, ImgDepth, ImgModCoeff,
934  MetaData2D, MetaDataDepth))
935  {
936  BIASERR("Could not Load XML-image.");
937  return -1;
938  }
939  vecImg2D.push_back(Img2D);
940  vecImgDepth.push_back(ImgDepth);
941  vecImgModCoeff.push_back(ImgModCoeff);
942  vecMetaData2D.push_back(MetaData2D);
943  vecMetaDataDepth.push_back(MetaDataDepth);
944  } else {
945  BIASERR("Root node has to be \"frame\" or \"sequence\"");
946  return -1;
947  }
948  }
949  return 0;
950 }
951 
952 
953 #endif
954 
955 
956 int PMDImageIO::LoadFromTIFF(const std::string& FileName,
957  Image<unsigned char> &Img2D,
958  Image<float> &ImgDepth,
959  Image<float> &ImgModCoeff,
960  PMDImageMetaData &MetaData2D,
961  PMDImageMetaData &MetaDataDepth) {
962 
963  uint8* data2d=NULL;
964  uint16* dataDepth=NULL;
965  uint16* dataModCoeff=NULL;
966 
967  if (PMDImageIO::Load(FileName, data2d, dataDepth, dataModCoeff,
968  MetaData2D, MetaDataDepth)<0) {
969  BIASERR("Could not Load TIFF-image.");
970  return -1;
971  }
972  return PostprocessData_(data2d, dataDepth, dataModCoeff,
973  Img2D, ImgDepth, ImgModCoeff,
974  MetaData2D, MetaDataDepth);
975 }
976 
977 
978 int PMDImageIO::LoadFromTXT(int width, int height,
979  const std::string& FileName2D,
980  const std::string& FileNameDepth,
981  const std::string& FileNameModCoeff,
982  Image<unsigned char> &Img2D,
983  Image<float> &ImgDepth,
984  Image<float> &ImgModCoeff,
985  PMDImageMetaData &MetaDataDepth) {
986 
987  // open file streams
988  ifstream in2D(FileName2D.c_str());
989  if (!in2D) {
990  BIASERR("Error opening 2D file:"<<FileName2D);
991  return -1;
992  }
993  ifstream inDepth(FileNameDepth.c_str());
994  if (!inDepth) {
995  BIASERR("Error opening Depth file:"<<FileNameDepth);
996  return -1;
997  }
998  ifstream inModCoeff(FileNameModCoeff.c_str());
999  if (!inModCoeff) {
1000  BIASERR("Error opening ModCoeff file:"<<FileNameModCoeff);
1001  return -1;
1002  }
1003 
1004  uint8* data2d = NULL;
1005  uint16* data2d16 = new uint16[width*height];
1006  uint16* dataDepth = new uint16[width*height];
1007  uint16* dataModCoeff = new uint16[width*height];
1008 
1009  double d;
1010  for (int i=0; i<width*height; i++) {
1011  in2D >> d;
1012  data2d16[i] = uint16(d);
1013  inDepth >> d;
1014  dataDepth[i] = uint16(d);
1015  inModCoeff >> d;
1016  dataModCoeff[i] = uint16(d);
1017  }
1018  MetaDataDepth.width = width;
1019  MetaDataDepth.height = height;
1020  MetaDataDepth.channels = 1;
1021  MetaDataDepth.PrincipalX = (double)width/2.0;
1022  MetaDataDepth.PrincipalY = (double)height/2.0;
1023  MetaDataDepth.FocallengthX = 1;
1024  MetaDataDepth.AspectRatio = 1;
1025  MetaDataDepth.UndistCoeff[0] = 0;
1026  MetaDataDepth.UndistCoeff[1] = 0;
1027  MetaDataDepth.UndistCoeff[2] = 0;
1028  MetaDataDepth.UndistCoeff[3] = 0;
1029  MetaDataDepth.CameraCenter[0] = 0;
1030  MetaDataDepth.CameraCenter[1] = 0;
1031  MetaDataDepth.CameraCenter[2] = 0;
1032  MetaDataDepth.CameraRotation[0] = 0;
1033  MetaDataDepth.CameraRotation[1] = 0;
1034  MetaDataDepth.CameraRotation[2] = 0;
1035  Grey16to8Bit_(data2d16, data2d,
1036  width*height);
1037  PostprocessData_(data2d, dataDepth, dataModCoeff,
1038  Img2D, ImgDepth, ImgModCoeff,
1039  MetaDataDepth, MetaDataDepth);
1040 
1041  //delete [] data2d;
1042  //delete [] data2d16;
1043  //delete [] dataDepth;
1044  //delete [] dataModCoeff;
1045 
1046  return 0;
1047 
1048 }
1049 
1050 int PMDImageIO::GetBitRep(const std::string& FileName) {
1051  TIFF *tiffimage;
1052 
1053  if((tiffimage = TIFFOpen(FileName.c_str(), "r")) == NULL){
1054  BIASERR("Could not open image for Loading:" << FileName);
1055  return -1;
1056  }
1057 
1058  do {
1059  char* descr;
1060  if (TIFFGetField(tiffimage, TIFFTAG_IMAGEDESCRIPTION, &descr) == 0) {
1061  BIASERR("Image description is missing!");
1062  return -1;
1063  }
1064  if(strcmp(descr, "2D-Image") == 0) {
1065  uint16 bps;
1066  if (TIFFGetField(tiffimage, TIFFTAG_BITSPERSAMPLE, &bps)<0) {
1067  return -1;
1068  } else {
1069  return bps;
1070  }
1071  }
1072  } while (TIFFReadDirectory(tiffimage)!=0);
1073 
1074  return 0;
1075 }
1076 
1077 
1078 void PMDImageIO::Grey16to8Bit_(uint16* src, uint8* &dst,
1079  unsigned int size)
1080 {
1081  dst = new unsigned char[size];
1082  uint16 min = 65535;
1083  uint16 max = 0;
1084  uint16* p16 = src;
1085  for (unsigned int i=0; i<size; i++) {
1086  if ((*p16)<min) min=*p16;
1087  if ((*p16)>max) max=*p16;
1088  p16++;
1089  }
1090  p16 = src;
1091  uint8* p8 = dst;
1092  for (unsigned int i=0; i<size; i++) {
1093  (*p8) = (unsigned char)((double)((*p16)-min)/(double)(max-min)*255.0);
1094  p8++;
1095  p16++;
1096  }
1097 }
1098 
1099 uint16 PMDImageIO::Convert_(float val, float lower, float upper) {
1100  float step=(upper-lower)/UINT16_MAX;
1101  if (val < lower) return 0;
1102  if (val > upper) return UINT16_MAX;
1103  return (uint16)((val-lower)/step);
1104 }
1105 
1106 float PMDImageIO::Convert_(uint16 val, float lower, float upper)
1107 {
1108  float step=(upper-lower)/UINT16_MAX;
1109  return val*step+lower;
1110 }
1111 
1112 
1113 
1114 uint16 PMDImageIO::DepthConvert_(float depth) {
1115  return Convert_(depth, DEPTH_MIN, DEPTH_MAX);
1116 }
1117 
1118 
1119 float PMDImageIO::DepthConvert_(uint16 depth) {
1120  return Convert_(depth, DEPTH_MIN, DEPTH_MAX);
1121 }
1122 
1123 
1124 uint16 PMDImageIO::ModCoeffConvert_(float modcoeff) {
1125  return Convert_(modcoeff, MODCOEFF_MIN, MODCOEFF_MAX);
1126 }
1127 
1128 float PMDImageIO::ModCoeffConvert_(uint16 modcoeff) {
1129  return Convert_(modcoeff, MODCOEFF_MIN, MODCOEFF_MAX);
1130 }
1131 
1132 
1133 int PMDImageIO::PostprocessData_(uint8* data2d, uint16* dataDepth,
1134  uint16* dataModCoeff,
1135  Image<unsigned char> &Img2D,
1136  Image<float> &ImgDepth,
1137  Image<float> &ImgModCoeff,
1138  PMDImageMetaData &MetaData2D,
1139  PMDImageMetaData &MetaDataDepth) {
1140  int ret=0, ret2=0, ret3=0;
1141 
1142  if (data2d!=NULL) {
1143  if (!Img2D.IsEmpty()) Img2D.Release();
1144  ret = Img2D.InitWithForeignData(MetaData2D.width, MetaData2D.height,
1145  MetaData2D.channels,
1146  (unsigned char*) data2d);
1147  if (ret!=0) BIASERR("Error Loading 2D image" << ret);
1148 
1149  if (MetaData2D.channels==3) {
1150  Img2D.SetColorModel(ImageBase::CM_RGB);
1151  } else {
1152  Img2D.SetColorModel(ImageBase::CM_Grey);
1153  }
1154 
1155  }
1156 
1157  if (dataDepth!=NULL) {
1158  float *dataDepthf = new float[MetaDataDepth.width*MetaDataDepth.height];
1159  float *pDataDepthf = dataDepthf;
1160  uint16* pDataDepth = dataDepth;
1161  for (unsigned int i=0; i<MetaDataDepth.width*MetaDataDepth.height;
1162  i++, pDataDepthf++, pDataDepth++) {
1163  *pDataDepthf = DepthConvert_(*pDataDepth);
1164  }
1165  if (!ImgDepth.IsEmpty()) ImgDepth.Release();
1166  ret2 = ImgDepth.InitWithForeignData(MetaDataDepth.width,
1167  MetaDataDepth.height,
1168  MetaDataDepth.channels,
1169  dataDepthf);
1170  delete [] dataDepth;
1171  if (ret2!=0) BIASERR("Error Loading Depth image" << ret2);
1172  }
1173 
1174  if (dataModCoeff!=NULL) {
1175  float *dataModCoefff = new float[MetaDataDepth.width*MetaDataDepth.height];
1176  float *pDataModCoefff = dataModCoefff;
1177  uint16* pDataModCoeff = dataModCoeff;
1178  for (unsigned int i=0; i<MetaDataDepth.width*MetaDataDepth.height;
1179  i++, pDataModCoefff++, pDataModCoeff++) {
1180  *pDataModCoefff = ModCoeffConvert_(*pDataModCoeff);
1181  }
1182  if (!ImgModCoeff.IsEmpty()) ImgModCoeff.Release();
1183  ret3 = ImgModCoeff.InitWithForeignData(MetaDataDepth.width,
1184  MetaDataDepth.height,
1185  MetaDataDepth.channels,
1186  dataModCoefff);
1187  delete [] dataModCoeff;
1188  if (ret3!=0) BIASERR("Error Loading Modulation Coefficients image"
1189  << ret3);
1190  }
1191  return ret+ret2+ret3;
1192 }
1193 
1194 
1195 int PMDImageIO::LoadMetaData_(TIFF* tiffimage, PMDImageMetaData &MetaData) {
1196 
1197  double* cont=NULL;
1198  int16 count;
1199  uint16 channels;
1200  uint32 width, height;
1201 
1202  if(TIFFGetField(tiffimage, TIFFTAG_IMAGEWIDTH, &width) == 0){
1203  BIASERR("Image does not define its width");
1204  return -1;
1205  } else {
1206  MetaData.width = width;
1207  }
1208 
1209  if(TIFFGetField(tiffimage, TIFFTAG_IMAGELENGTH, &height) == 0){
1210  BIASERR("Image does not define its height");
1211  return -1;
1212  } else {
1213  MetaData.height = height;
1214  }
1215 
1216  if((TIFFGetField(tiffimage, TIFFTAG_SAMPLESPERPIXEL, &channels) == 0)){
1217  BIASERR("Wrong number of image planes!");
1218  return -1;
1219  } else {
1220  MetaData.channels =channels;
1221  }
1222 
1223  if(TIFFGetField(tiffimage, TIFFTAG_PRINCIPALPOINT, &count, &cont) == 0 ||
1224  (count!=2)){
1225  BIASERR("Error while Loading Principal point!");
1226  return -1;
1227  } else {
1228  MetaData.PrincipalX = cont[0];
1229  MetaData.PrincipalY = cont[1];
1230  }
1231 
1232  if(TIFFGetField(tiffimage, TIFFTAG_FOCALLENGTHX, &count, &cont) == 0 ||
1233  (count!=1)){
1234  BIASERR("Error while Loading focal length!");
1235  return -1;
1236  } else {
1237  MetaData.FocallengthX = cont[0];
1238  }
1239 
1240  if(TIFFGetField(tiffimage, TIFFTAG_ASPECTRATIO, &count, &cont) == 0 ||
1241  (count!=1)){
1242  BIASERR("Error while Loading aspectratio!");
1243  return -1;
1244  } else {
1245  MetaData.AspectRatio = cont[0];
1246  }
1247 
1248  if(TIFFGetField(tiffimage, TIFFTAG_UNDISTORTION, &count, &cont) == 0 ||
1249  (count!=4)){
1250  BIASERR("Error while Loading bouget undistortion parameters!");
1251  return -1;
1252  } else {
1253  MetaData.UndistCoeff[0] = cont[0];
1254  MetaData.UndistCoeff[1] = cont[1];
1255  MetaData.UndistCoeff[2] = cont[2];
1256  MetaData.UndistCoeff[3] = cont[3];
1257  }
1258 
1259  if(TIFFGetField(tiffimage, TIFFTAG_CAMERACENTER, &count, &cont) == 0 ||
1260  (count!=3)){
1261  BIASERR("Error while Loading camera center!");
1262  return -1;
1263  } else {
1264  MetaData.CameraCenter[0] = cont[0];
1265  MetaData.CameraCenter[1] = cont[1];
1266  MetaData.CameraCenter[2] = cont[2];
1267  }
1268 
1269  if(TIFFGetField(tiffimage, TIFFTAG_CAMERAROTATION, &count, &cont) == 0 ||
1270  (count!=3)){
1271  BIASERR("Error while Loading camera rotation!");
1272  return -1;
1273  } else {
1274  MetaData.CameraRotation[0] = cont[0];
1275  MetaData.CameraRotation[1] = cont[1];
1276  MetaData.CameraRotation[2] = cont[2];
1277  }
1278 
1279  return 0;
1280 }
1281 
1282 int PMDImageIO::SaveMetaData_(TIFF* tiffimage,
1283  const PMDImageMetaData &MetaData) {
1284 
1285  double princ[] = {MetaData.PrincipalX, MetaData.PrincipalY};
1286  TIFFSetField(tiffimage, TIFFTAG_PRINCIPALPOINT, 2, &princ);
1287  double f[] = {MetaData.FocallengthX};
1288  TIFFSetField(tiffimage, TIFFTAG_FOCALLENGTHX, 1, &f);
1289  double a[] = {MetaData.AspectRatio};
1290  TIFFSetField(tiffimage, TIFFTAG_ASPECTRATIO, 1, &a);
1291  TIFFSetField(tiffimage, TIFFTAG_UNDISTORTION, 4, &MetaData.UndistCoeff);
1292  TIFFSetField(tiffimage, TIFFTAG_CAMERACENTER, 3, &MetaData.CameraCenter);
1293  TIFFSetField(tiffimage, TIFFTAG_CAMERAROTATION, 3,
1294  &MetaData.CameraRotation);
1295 
1296  return 0;
1297 }
1298 
1299 
1300 void PMDImageIO::NewTagsInitialize_()
1301 {
1302  static int first_time=1;
1303 
1304  if (! first_time)
1305  return; /* Been there. Done that. */
1306 
1307  first_time = 0;
1308 
1309  /* Grab the inherited method and install */
1310  ParentExtender = TIFFSetTagExtender(NewTagsCallback_);
1311 }
1312 
1313 
1314 void PMDImageIO::NewTagsCallback_(TIFF *tif) {
1315  /* Install the extended Tag field info */
1316  TIFFMergeFieldInfo(tif, tiffFieldInfo,
1317  sizeof(tiffFieldInfo)/sizeof(tiffFieldInfo[0]));
1318 
1319  /* Since the client module may have overridden
1320  * the default directory method, we call it now to
1321  * allow it to set up the rest of its own methods.
1322  */
1323 
1324  if (ParentExtender)
1325  (*ParentExtender)(tif);
1326 }
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
xmlNodePtr getNextChild()
Get the next child of the parent specified in the last getFirstChild() call, the class remembers the ...
Definition: XMLIO.cpp:466
xmlNodePtr read(const std::string &Filename)
Read and parse an XML file from disk, DtD validation is not yet implemented.
Definition: XMLIO.cpp:416
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
xmlNodePtr getChild(const xmlNodePtr ParentNode, const std::string &ChildName)
Get a child of a Parent node by specifying the childs name, NULL is returned if the ParentNode has no...
Definition: XMLIO.cpp:489
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
int InitWithForeignData(unsigned int width, unsigned int height, unsigned int channels, void *data, const bool interleaved=true, const bool shouldRelease=true)
This is used to construct a BIAS::Image hull around existing image data.
Definition: Image.cpp:1660
unsigned int GetWidth() const
Definition: ImageBase.hh:312
double CameraRotation[3]
Definition: PMDImageIO.hh:80
int getAttributeValueInt(const xmlAttrPtr Attribute) const
Definition: XMLIO.cpp:728
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
Definition: XMLIO.hh:72
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
unsigned int GetHeight() const
Definition: ImageBase.hh:319
unsigned int channels
Definition: PMDImageIO.hh:73
unsigned int width
Definition: PMDImageIO.hh:71
xmlNodePtr getFirstChild(const xmlNodePtr ParentNode)
Get the first child of a given parent, or NULL for no childs.
Definition: XMLIO.cpp:452
unsigned int height
Definition: PMDImageIO.hh:72
Store extrinsic and intrinsic camera parameters for Rotation is in axis * angle representation image ...
Definition: PMDImageIO.hh:70
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
double getAttributeValueDouble(const xmlAttrPtr Attribute) const
Definition: XMLIO.cpp:736
std::vector< int > getNodeContentVectorInt(const xmlNodePtr Node) const
Definition: XMLIO.cpp:587
this class collects all additional data chunks of type AppData to be written into/read from an image ...
Definition: MetaData.hh:121
std::string getNodeName(const xmlNodePtr Node) const
Get the name of a given Node.
Definition: XMLIO.cpp:543
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414