laswriter_las.cpp
Go to the documentation of this file.
1 /*
2 ===============================================================================
3 
4  FILE: laswriter_las.cpp
5 
6  CONTENTS:
7 
8  see corresponding header file
9 
10  PROGRAMMERS:
11 
12  martin.isenburg@gmail.com
13 
14  COPYRIGHT:
15 
16  (c) 2007-2011, Martin Isenburg, LASSO - tools to catch reality
17 
18  This is free software; you can redistribute and/or modify it under the
19  terms of the GNU Lesser General Licence as published by the Free Software
20  Foundation. See the COPYING file for more information.
21 
22  This software is distributed WITHOUT ANY WARRANTY and without even the
23  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 
25  CHANGE HISTORY:
26 
27  see corresponding header file
28 
29 ===============================================================================
30 */
31 #include "laswriter_las.hpp"
32 
33 #include "bytestreamout_nil.hpp"
34 #include "bytestreamout_file.hpp"
36 #include "laswritepoint.hpp"
37 
38 #ifdef _WIN32
39 #include <fcntl.h>
40 #include <io.h>
41 #endif
42 
43 #include <stdlib.h>
44 #include <string.h>
45 
47 {
48  if (stream == 0) return FALSE;
49  if (this->file) this->file = file;
50  return ((ByteStreamOutFile*)stream)->refile(file);
51 }
52 
53 BOOL LASwriterLAS::open(const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size)
54 {
55  ByteStreamOut* out = new ByteStreamOutNil();
56  return open(out, header, compressor, requested_version, chunk_size);
57 }
58 
59 BOOL LASwriterLAS::open(const char* file_name, const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size, U32 io_buffer_size)
60 {
61  if (file_name == 0)
62  {
63  fprintf(stderr,"ERROR: file name pointer is zero\n");
64  return FALSE;
65  }
66 
67  file = fopen(file_name, "wb");
68  if (file == 0)
69  {
70  fprintf(stderr, "ERROR: cannot open file '%s'\n", file_name);
71  return FALSE;
72  }
73 
74  if (setvbuf(file, NULL, _IOFBF, io_buffer_size) != 0)
75  {
76  fprintf(stderr, "WARNING: setvbuf() failed with buffer size %u\n", io_buffer_size);
77  }
78 
79  ByteStreamOut* out;
80  if (IS_LITTLE_ENDIAN())
81  out = new ByteStreamOutFileLE(file);
82  else
83  out = new ByteStreamOutFileBE(file);
84 
85  return open(out, header, compressor, requested_version, chunk_size);
86 }
87 
88 BOOL LASwriterLAS::open(FILE* file, const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size)
89 {
90  if (file == 0)
91  {
92  fprintf(stderr,"ERROR: file pointer is zero\n");
93  return FALSE;
94  }
95 
96 #ifdef _WIN32
97  if (file == stdout)
98  {
99  if(_setmode( _fileno( stdout ), _O_BINARY ) == -1 )
100  {
101  fprintf(stderr, "ERROR: cannot set stdout to binary (untranslated) mode\n");
102  }
103  }
104 #endif
105 
106  ByteStreamOut* out;
107  if (IS_LITTLE_ENDIAN())
108  out = new ByteStreamOutFileLE(file);
109  else
110  out = new ByteStreamOutFileBE(file);
111 
112  return open(out, header, compressor, requested_version, chunk_size);
113 }
114 
115 BOOL LASwriterLAS::open(ostream& stream, const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size)
116 {
117  ByteStreamOut* out;
118  if (IS_LITTLE_ENDIAN())
119  out = new ByteStreamOutOstreamLE(stream);
120  else
121  out = new ByteStreamOutOstreamBE(stream);
122 
123  return open(out, header, compressor, requested_version, chunk_size);
124 }
125 
126 BOOL LASwriterLAS::open(ByteStreamOut* stream, const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size)
127 {
128  U32 i;
129 
130  if (stream == 0)
131  {
132  fprintf(stderr,"ERROR: ByteStreamOut pointer is zero\n");
133  return FALSE;
134  }
135  this->stream = stream;
136 
137  if (header == 0)
138  {
139  fprintf(stderr,"ERROR: LASheader pointer is zero\n");
140  return FALSE;
141  }
142 
143  // check header contents
144 
145  if (!header->check()) return FALSE;
146 
147  // copy scale_and_offset
151  quantizer.x_offset = header->x_offset;
152  quantizer.y_offset = header->y_offset;
153  quantizer.z_offset = header->z_offset;
154 
155  // check if the requested point type is supported
156 
157  BOOL point_is_standard = TRUE;
158  U8 point_data_format;
159  U16 point_data_record_length;
160  LASpoint point;
161  if (header->laszip)
162  {
163  if (!point.init(&quantizer, header->laszip->num_items, header->laszip->items, header)) return FALSE;
164  point_is_standard = header->laszip->is_standard(&point_data_format, &point_data_record_length);
165  }
166  else
167  {
168  if (!point.init(&quantizer, header->point_data_format, header->point_data_record_length, header)) return FALSE;
169  point_data_format = header->point_data_format;
170  point_data_record_length = header->point_data_record_length;
171  }
172 
173  // do we need a laszip VLR (because we compress or use non-standard points?)
174 
175  LASzip* laszip = 0;
176  U32 laszip_vlr_data_size = 0;
177  if (compressor || point_is_standard == FALSE)
178  {
179  laszip = new LASzip();
180  laszip->setup(point.num_items, point.items, compressor);
181  if (chunk_size > -1) laszip->set_chunk_size((U32)chunk_size);
182  if (compressor == LASZIP_COMPRESSOR_NONE) laszip->request_version(0);
183  else if (requested_version) laszip->request_version(requested_version);
184  else laszip->request_version(2);
185  laszip_vlr_data_size = 34 + 6*laszip->num_items;
186  }
187 
188  // create and setup the point writer
189 
190  writer = new LASwritePoint();
191  if (laszip)
192  {
193  if (!writer->setup(laszip->num_items, laszip->items, laszip)) return FALSE;
194  }
195  else
196  {
197  if (!writer->setup(point.num_items, point.items)) return FALSE;
198  }
199 
200  // save the position where we start writing the header
201 
203 
204  // write header variable after variable (to avoid alignment issues)
205 
206  if (!stream->putBytes((U8*)&(header->file_signature), 4))
207  {
208  fprintf(stderr,"ERROR: writing header->file_signature\n");
209  return FALSE;
210  }
211  if (!stream->put16bitsLE((U8*)&(header->file_source_id)))
212  {
213  fprintf(stderr,"ERROR: writing header->file_source_id\n");
214  return FALSE;
215  }
216  if (!stream->put16bitsLE((U8*)&(header->global_encoding)))
217  {
218  fprintf(stderr,"ERROR: writing header->global_encoding\n");
219  return FALSE;
220  }
221  if (!stream->put32bitsLE((U8*)&(header->project_ID_GUID_data_1)))
222  {
223  fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_1\n");
224  return FALSE;
225  }
226  if (!stream->put16bitsLE((U8*)&(header->project_ID_GUID_data_2)))
227  {
228  fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_2\n");
229  return FALSE;
230  }
231  if (!stream->put16bitsLE((U8*)&(header->project_ID_GUID_data_3)))
232  {
233  fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_3\n");
234  return FALSE;
235  }
236  if (!stream->putBytes((U8*)&(header->project_ID_GUID_data_4), 8))
237  {
238  fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_4\n");
239  return FALSE;
240  }
241  // check version major
242  if (header->version_major != 1)
243  {
244  fprintf(stderr,"WARNING: header->version_major is %d. writing 1 instead.\n", header->version_major);
245  if (!stream->putByte(1))
246  {
247  fprintf(stderr,"ERROR: writing header->version_major\n");
248  return FALSE;
249  }
250  }
251  else
252  {
253  if (!stream->putByte(header->version_major))
254  {
255  fprintf(stderr,"ERROR: writing header->version_major\n");
256  return FALSE;
257  }
258  }
259  // check version major
260  if (header->version_minor > 4)
261  {
262  fprintf(stderr,"WARNING: header->version_minor is %d. writing 4 instead.\n", header->version_minor);
263  if (!stream->putByte(4))
264  {
265  fprintf(stderr,"ERROR: writing header->version_minor\n");
266  return FALSE;
267  }
268  }
269  else
270  {
271  if (!stream->putByte(header->version_minor))
272  {
273  fprintf(stderr,"ERROR: writing header->version_minor\n");
274  return FALSE;
275  }
276  }
277  if (!stream->putBytes((U8*)&(header->system_identifier), 32))
278  {
279  fprintf(stderr,"ERROR: writing header->system_identifier\n");
280  return FALSE;
281  }
282  if (!stream->putBytes((U8*)&(header->generating_software), 32))
283  {
284  fprintf(stderr,"ERROR: writing header->generating_software\n");
285  return FALSE;
286  }
287  if (!stream->put16bitsLE((U8*)&(header->file_creation_day)))
288  {
289  fprintf(stderr,"ERROR: writing header->file_creation_day\n");
290  return FALSE;
291  }
292  if (!stream->put16bitsLE((U8*)&(header->file_creation_year)))
293  {
294  fprintf(stderr,"ERROR: writing header->file_creation_year\n");
295  return FALSE;
296  }
297  if (!stream->put16bitsLE((U8*)&(header->header_size)))
298  {
299  fprintf(stderr,"ERROR: writing header->header_size\n");
300  return FALSE;
301  }
302  U32 offset_to_point_data = header->offset_to_point_data;
303  if (laszip) offset_to_point_data += (54 + laszip_vlr_data_size);
304  if (header->vlr_lastiling) offset_to_point_data += (54 + 28);
305  if (!stream->put32bitsLE((U8*)&offset_to_point_data))
306  {
307  fprintf(stderr,"ERROR: writing header->offset_to_point_data\n");
308  return FALSE;
309  }
310  U32 number_of_variable_length_records = header->number_of_variable_length_records;
311  if (laszip) number_of_variable_length_records++;
312  if (header->vlr_lastiling) number_of_variable_length_records++;
313  if (!stream->put32bitsLE((U8*)&(number_of_variable_length_records)))
314  {
315  fprintf(stderr,"ERROR: writing header->number_of_variable_length_records\n");
316  return FALSE;
317  }
318  if (compressor) point_data_format |= 128;
319  if (!stream->putByte(point_data_format))
320  {
321  fprintf(stderr,"ERROR: writing header->point_data_format\n");
322  return FALSE;
323  }
324  if (!stream->put16bitsLE((U8*)&(header->point_data_record_length)))
325  {
326  fprintf(stderr,"ERROR: writing header->point_data_record_length\n");
327  return FALSE;
328  }
329  if (!stream->put32bitsLE((U8*)&(header->number_of_point_records)))
330  {
331  fprintf(stderr,"ERROR: writing header->number_of_point_records\n");
332  return FALSE;
333  }
334  for (i = 0; i < 5; i++)
335  {
336  if (!stream->put32bitsLE((U8*)&(header->number_of_points_by_return[i])))
337  {
338  fprintf(stderr,"ERROR: writing header->number_of_points_by_return[%d]\n", i);
339  return FALSE;
340  }
341  }
342  if (!stream->put64bitsLE((U8*)&(header->x_scale_factor)))
343  {
344  fprintf(stderr,"ERROR: writing header->x_scale_factor\n");
345  return FALSE;
346  }
347  if (!stream->put64bitsLE((U8*)&(header->y_scale_factor)))
348  {
349  fprintf(stderr,"ERROR: writing header->y_scale_factor\n");
350  return FALSE;
351  }
352  if (!stream->put64bitsLE((U8*)&(header->z_scale_factor)))
353  {
354  fprintf(stderr,"ERROR: writing header->z_scale_factor\n");
355  return FALSE;
356  }
357  if (!stream->put64bitsLE((U8*)&(header->x_offset)))
358  {
359  fprintf(stderr,"ERROR: writing header->x_offset\n");
360  return FALSE;
361  }
362  if (!stream->put64bitsLE((U8*)&(header->y_offset)))
363  {
364  fprintf(stderr,"ERROR: writing header->y_offset\n");
365  return FALSE;
366  }
367  if (!stream->put64bitsLE((U8*)&(header->z_offset)))
368  {
369  fprintf(stderr,"ERROR: writing header->z_offset\n");
370  return FALSE;
371  }
372  if (!stream->put64bitsLE((U8*)&(header->max_x)))
373  {
374  fprintf(stderr,"ERROR: writing header->max_x\n");
375  return FALSE;
376  }
377  if (!stream->put64bitsLE((U8*)&(header->min_x)))
378  {
379  fprintf(stderr,"ERROR: writing header->min_x\n");
380  return FALSE;
381  }
382  if (!stream->put64bitsLE((U8*)&(header->max_y)))
383  {
384  fprintf(stderr,"ERROR: writing header->max_y\n");
385  return FALSE;
386  }
387  if (!stream->put64bitsLE((U8*)&(header->min_y)))
388  {
389  fprintf(stderr,"ERROR: writing header->min_y\n");
390  return FALSE;
391  }
392  if (!stream->put64bitsLE((U8*)&(header->max_z)))
393  {
394  fprintf(stderr,"ERROR: writing header->max_z\n");
395  return FALSE;
396  }
397  if (!stream->put64bitsLE((U8*)&(header->min_z)))
398  {
399  fprintf(stderr,"ERROR: writing header->min_z\n");
400  return FALSE;
401  }
402 
403  // special handling for LAS 1.3 or higher.
404  if (header->version_minor >= 3)
405  {
406  // nobody currently includes waveform. we set the field always to zero
407  if (header->start_of_waveform_data_packet_record != 0)
408  {
409 #ifdef _WIN32
410  fprintf(stderr,"WARNING: header->start_of_waveform_data_packet_record is %I64d. writing 0 instead.\n", header->start_of_waveform_data_packet_record);
411 #else
412  fprintf(stderr,"WARNING: header->start_of_waveform_data_packet_record is %lld. writing 0 instead.\n", header->start_of_waveform_data_packet_record);
413 #endif
414  U64 start_of_waveform_data_packet_record = 0;
415  if (!stream->put64bitsLE((U8*)&start_of_waveform_data_packet_record))
416  {
417  fprintf(stderr,"ERROR: writing start_of_waveform_data_packet_record\n");
418  return FALSE;
419  }
420  }
421  else
422  {
424  {
425  fprintf(stderr,"ERROR: writing header->start_of_waveform_data_packet_record\n");
426  return FALSE;
427  }
428  }
429  }
430 
431  // special handling for LAS 1.4 or higher.
432  if (header->version_minor >= 4)
433  {
435  {
436  fprintf(stderr,"ERROR: writing header->start_of_first_extended_variable_length_record\n");
437  return FALSE;
438  }
440  {
441  fprintf(stderr,"ERROR: writing header->number_of_extended_variable_length_records\n");
442  return FALSE;
443  }
444  U64 value;
445  if (header->number_of_point_records)
446  value = header->number_of_point_records;
447  else
448  value = header->extended_number_of_point_records;
449  if (!stream->put64bitsLE((U8*)&value))
450  {
451  fprintf(stderr,"ERROR: writing header->extended_number_of_point_records\n");
452  return FALSE;
453  }
454  for (i = 0; i < 15; i++)
455  {
456  if ((i < 5) && header->number_of_points_by_return[i])
457  value = header->number_of_points_by_return[i];
458  else
459  value = header->extended_number_of_points_by_return[i];
460  if (!stream->put64bitsLE((U8*)&value))
461  {
462  fprintf(stderr,"ERROR: writing header->extended_number_of_points_by_return[%d]\n", i);
463  return FALSE;
464  }
465  }
466  }
467 
468  // write any number of user-defined bytes that might have been added into the header
469 
470  if (header->user_data_in_header_size)
471  {
472  if (header->user_data_in_header)
473  {
475  {
476  fprintf(stderr,"ERROR: writing %d bytes of data from header->user_data_in_header\n", header->user_data_in_header_size);
477  return FALSE;
478  }
479  }
480  else
481  {
482  fprintf(stderr,"ERROR: there should be %d bytes of data in header->user_data_in_header\n", header->user_data_in_header_size);
483  return FALSE;
484  }
485  }
486 
487  // write variable length records variable after variable (to avoid alignment issues)
488 
489  for (i = 0; i < header->number_of_variable_length_records; i++)
490  {
491  // check variable length records contents
492 
493  if (header->vlrs[i].reserved != 0xAABB)
494  {
495 // fprintf(stderr,"WARNING: wrong header->vlrs[%d].reserved: %d != 0xAABB\n", i, header->vlrs[i].reserved);
496  }
497 
498  // write variable length records variable after variable (to avoid alignment issues)
499 
500  if (!stream->put16bitsLE((U8*)&(header->vlrs[i].reserved)))
501  {
502  fprintf(stderr,"ERROR: writing header->vlrs[%d].reserved\n", i);
503  return FALSE;
504  }
505  if (!stream->putBytes((U8*)header->vlrs[i].user_id, 16))
506  {
507  fprintf(stderr,"ERROR: writing header->vlrs[%d].user_id\n", i);
508  return FALSE;
509  }
510  if (!stream->put16bitsLE((U8*)&(header->vlrs[i].record_id)))
511  {
512  fprintf(stderr,"ERROR: writing header->vlrs[%d].record_id\n", i);
513  return FALSE;
514  }
515  if (!stream->put16bitsLE((U8*)&(header->vlrs[i].record_length_after_header)))
516  {
517  fprintf(stderr,"ERROR: writing header->vlrs[%d].record_length_after_header\n", i);
518  return FALSE;
519  }
520  if (!stream->putBytes((U8*)header->vlrs[i].description, 32))
521  {
522  fprintf(stderr,"ERROR: writing header->vlrs[%d].description\n", i);
523  return FALSE;
524  }
525 
526  // write the data following the header of the variable length record
527 
528  if (header->vlrs[i].record_length_after_header)
529  {
530  if (header->vlrs[i].data)
531  {
532  if (!stream->putBytes((U8*)header->vlrs[i].data, header->vlrs[i].record_length_after_header))
533  {
534  fprintf(stderr,"ERROR: writing %d bytes of data from header->vlrs[%d].data\n", header->vlrs[i].record_length_after_header, i);
535  return FALSE;
536  }
537  }
538  else
539  {
540  fprintf(stderr,"ERROR: there should be %d bytes of data in header->vlrs[%d].data\n", header->vlrs[i].record_length_after_header, i);
541  return FALSE;
542  }
543  }
544  }
545 
546  // write laszip VLR with compression parameters
547 
548  if (laszip)
549  {
550  // write variable length records variable after variable (to avoid alignment issues)
551 
552  U16 reserved = 0xAABB;
553  if (!stream->put16bitsLE((U8*)&(reserved)))
554  {
555  fprintf(stderr,"ERROR: writing reserved %d\n", (I32)reserved);
556  return FALSE;
557  }
558  U8 user_id[16] = "laszip encoded\0";
559  if (!stream->putBytes((U8*)user_id, 16))
560  {
561  fprintf(stderr,"ERROR: writing user_id %s\n", user_id);
562  return FALSE;
563  }
564  U16 record_id = 22204;
565  if (!stream->put16bitsLE((U8*)&(record_id)))
566  {
567  fprintf(stderr,"ERROR: writing record_id %d\n", (I32)record_id);
568  return FALSE;
569  }
570  U16 record_length_after_header = laszip_vlr_data_size;
571  if (!stream->put16bitsLE((U8*)&(record_length_after_header)))
572  {
573  fprintf(stderr,"ERROR: writing record_length_after_header %d\n", (I32)record_length_after_header);
574  return FALSE;
575  }
576  char description[32];
577  memset(description, 0, 32);
578  sprintf(description, "by laszip of LAStools (%d)", LAS_TOOLS_VERSION);
579  if (!stream->putBytes((U8*)description, 32))
580  {
581  fprintf(stderr,"ERROR: writing description %s\n", description);
582  return FALSE;
583  }
584  // write the data following the header of the variable length record
585  // U16 compressor 2 bytes
586  // U16 coder 2 bytes
587  // U8 version_major 1 byte
588  // U8 version_minor 1 byte
589  // U16 version_revision 2 bytes
590  // U32 options 4 bytes
591  // U32 chunk_size 4 bytes
592  // I64 num_points 8 bytes
593  // I64 num_bytes 8 bytes
594  // U16 num_items 2 bytes
595  // U16 type 2 bytes * num_items
596  // U16 size 2 bytes * num_items
597  // U16 version 2 bytes * num_items
598  // which totals 34+6*num_items
599 
600  if (!stream->put16bitsLE((U8*)&(laszip->compressor)))
601  {
602  fprintf(stderr,"ERROR: writing compressor %d\n", (I32)compressor);
603  return FALSE;
604  }
605  if (!stream->put16bitsLE((U8*)&(laszip->coder)))
606  {
607  fprintf(stderr,"ERROR: writing coder %d\n", (I32)laszip->coder);
608  return FALSE;
609  }
610  if (!stream->putByte(laszip->version_major))
611  {
612  fprintf(stderr,"ERROR: writing version_major %d\n", laszip->version_major);
613  return FALSE;
614  }
615  if (!stream->putByte(laszip->version_minor))
616  {
617  fprintf(stderr,"ERROR: writing version_minor %d\n", laszip->version_minor);
618  return FALSE;
619  }
620  if (!stream->put16bitsLE((U8*)&(laszip->version_revision)))
621  {
622  fprintf(stderr,"ERROR: writing version_revision %d\n", laszip->version_revision);
623  return FALSE;
624  }
625  if (!stream->put32bitsLE((U8*)&(laszip->options)))
626  {
627  fprintf(stderr,"ERROR: writing options %d\n", (I32)laszip->options);
628  return FALSE;
629  }
630  if (!stream->put32bitsLE((U8*)&(laszip->chunk_size)))
631  {
632  fprintf(stderr,"ERROR: writing chunk_size %d\n", laszip->chunk_size);
633  return FALSE;
634  }
635  if (!stream->put64bitsLE((U8*)&(laszip->num_points)))
636  {
637  fprintf(stderr,"ERROR: writing num_points %d\n", (I32)laszip->num_points);
638  return FALSE;
639  }
640  if (!stream->put64bitsLE((U8*)&(laszip->num_bytes)))
641  {
642  fprintf(stderr,"ERROR: writing num_bytes %d\n", (I32)laszip->num_bytes);
643  return FALSE;
644  }
645  if (!stream->put16bitsLE((U8*)&(laszip->num_items)))
646  {
647  fprintf(stderr,"ERROR: writing num_items %d\n", laszip->num_items);
648  return FALSE;
649  }
650  for (i = 0; i < laszip->num_items; i++)
651  {
652  if (!stream->put16bitsLE((U8*)&(laszip->items[i].type)))
653  {
654  fprintf(stderr,"ERROR: writing type %d of item %d\n", laszip->items[i].type, i);
655  return FALSE;
656  }
657  if (!stream->put16bitsLE((U8*)&(laszip->items[i].size)))
658  {
659  fprintf(stderr,"ERROR: writing size %d of item %d\n", laszip->items[i].size, i);
660  return FALSE;
661  }
662  if (!stream->put16bitsLE((U8*)&(laszip->items[i].version)))
663  {
664  fprintf(stderr,"ERROR: writing version %d of item %d\n", laszip->items[i].version, i);
665  return FALSE;
666  }
667  }
668  }
669 
670  // write laszip VLR with compression parameters
671 
672  if (header->vlr_lastiling)
673  {
674  // write variable length records variable after variable (to avoid alignment issues)
675 
676  U16 reserved = 0xAABB;
677  if (!stream->put16bitsLE((U8*)&(reserved)))
678  {
679  fprintf(stderr,"ERROR: writing reserved %d\n", (I32)reserved);
680  return FALSE;
681  }
682  U8 user_id[16] = "lastools tile\0\0";
683  if (!stream->putBytes((U8*)user_id, 16))
684  {
685  fprintf(stderr,"ERROR: writing user_id %s\n", user_id);
686  return FALSE;
687  }
688  U16 record_id = 22204;
689  if (!stream->put16bitsLE((U8*)&(record_id)))
690  {
691  fprintf(stderr,"ERROR: writing record_id %d\n", (I32)record_id);
692  return FALSE;
693  }
694  U16 record_length_after_header = 28;
695  if (!stream->put16bitsLE((U8*)&(record_length_after_header)))
696  {
697  fprintf(stderr,"ERROR: writing record_length_after_header %d\n", (I32)record_length_after_header);
698  return FALSE;
699  }
700  U8 description[32] = "LAStools tile for streaming TIN";
701  if (!stream->putBytes((U8*)description, 32))
702  {
703  fprintf(stderr,"ERROR: writing description %s\n", description);
704  return FALSE;
705  }
706 
707  // write the data following the header of the variable length record
708  // U32 level 4 bytes
709  // U32 level_index 4 bytes
710  // U32 implicit_levels + overlap bit + reversible bit 4 bytes
711  // F32 min_x 4 bytes
712  // F32 max_x 4 bytes
713  // F32 min_y 4 bytes
714  // F32 max_y 4 bytes
715  // which totals 28 bytes
716 
717  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->level)))
718  {
719  fprintf(stderr,"ERROR: writing header->vlr_lastiling->level %u\n", header->vlr_lastiling->level);
720  return FALSE;
721  }
722  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->level_index)))
723  {
724  fprintf(stderr,"ERROR: writing header->vlr_lastiling->level_index %u\n", header->vlr_lastiling->level_index);
725  return FALSE;
726  }
727  if (!stream->put32bitsLE(((U8*)header->vlr_lastiling)+8))
728  {
729  fprintf(stderr,"ERROR: writing header->vlr_lastiling->implicit_levels %u\n", header->vlr_lastiling->implicit_levels);
730  return FALSE;
731  }
732  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->min_x)))
733  {
734  fprintf(stderr,"ERROR: writing header->vlr_lastiling->min_x %g\n", header->vlr_lastiling->min_x);
735  return FALSE;
736  }
737  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->max_x)))
738  {
739  fprintf(stderr,"ERROR: writing header->vlr_lastiling->max_x %g\n", header->vlr_lastiling->max_x);
740  return FALSE;
741  }
742  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->min_y)))
743  {
744  fprintf(stderr,"ERROR: writing header->vlr_lastiling->min_y %g\n", header->vlr_lastiling->min_y);
745  return FALSE;
746  }
747  if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->max_y)))
748  {
749  fprintf(stderr,"ERROR: writing header->vlr_lastiling->max_y %g\n", header->vlr_lastiling->max_y);
750  return FALSE;
751  }
752  }
753 
754  // write any number of user-defined bytes that might have been added after the header
755 
756  if (header->user_data_after_header_size)
757  {
758  if (header->user_data_after_header)
759  {
761  {
762  fprintf(stderr,"ERROR: writing %d bytes of data from header->user_data_after_header\n", header->user_data_after_header_size);
763  return FALSE;
764  }
765  }
766  else
767  {
768  fprintf(stderr,"ERROR: there should be %d bytes of data in header->user_data_after_header\n", header->user_data_after_header_size);
769  return FALSE;
770  }
771  }
772 
773  // initialize the point writer
774 
775  if (!writer->init(stream)) return FALSE;
776 
778  p_count = 0;
779 
780  return TRUE;
781 }
782 
784 {
785  p_count++;
786  return writer->write(point->point);
787 }
788 
790 {
791  return writer->chunk();
792 }
793 
794 BOOL LASwriterLAS::update_header(const LASheader* header, BOOL use_inventory, BOOL update_extra_bytes)
795 {
796  I32 i;
797  if (header == 0)
798  {
799  fprintf(stderr,"ERROR: header pointer is zero\n");
800  return FALSE;
801  }
802  if (stream == 0)
803  {
804  fprintf(stderr,"ERROR: stream pointer is zero\n");
805  return FALSE;
806  }
807  if (!stream->isSeekable())
808  {
809  fprintf(stderr,"ERROR: stream is not seekable\n");
810  return FALSE;
811  }
812  if (use_inventory && inventory.active())
813  {
816  {
817  fprintf(stderr,"ERROR: updating header->number_of_point_records\n");
818  return FALSE;
819  }
821  for (i = 0; i < 5; i++)
822  {
824  {
825  fprintf(stderr,"ERROR: updating header->number_of_points_by_return[%d]\n", i);
826  return FALSE;
827  }
828  }
830  F64 value;
831  value = header->get_x(inventory.raw_max_x);
832  if (!stream->put64bitsLE((U8*)&value))
833  {
834  fprintf(stderr,"ERROR: updating header->max_x\n");
835  return FALSE;
836  }
837  value = header->get_x(inventory.raw_min_x);
838  if (!stream->put64bitsLE((U8*)&value))
839  {
840  fprintf(stderr,"ERROR: updating header->min_x\n");
841  return FALSE;
842  }
843  value = header->get_y(inventory.raw_max_y);
844  if (!stream->put64bitsLE((U8*)&value))
845  {
846  fprintf(stderr,"ERROR: updating header->max_y\n");
847  return FALSE;
848  }
849  value = header->get_y(inventory.raw_min_y);
850  if (!stream->put64bitsLE((U8*)&value))
851  {
852  fprintf(stderr,"ERROR: updating header->min_y\n");
853  return FALSE;
854  }
855  value = header->get_z(inventory.raw_max_z);
856  if (!stream->put64bitsLE((U8*)&value))
857  {
858  fprintf(stderr,"ERROR: updating header->max_z\n");
859  return FALSE;
860  }
861  value = header->get_z(inventory.raw_min_z);
862  if (!stream->put64bitsLE((U8*)&value))
863  {
864  fprintf(stderr,"ERROR: updating header->min_z\n");
865  return FALSE;
866  }
867  }
868  else
869  {
871  if (!stream->put32bitsLE((U8*)&(header->number_of_point_records)))
872  {
873  fprintf(stderr,"ERROR: updating header->number_of_point_records\n");
874  return FALSE;
875  }
877  for (i = 0; i < 5; i++)
878  {
879  if (!stream->put32bitsLE((U8*)&(header->number_of_points_by_return[i])))
880  {
881  fprintf(stderr,"ERROR: updating header->number_of_points_by_return[%d]\n", i);
882  return FALSE;
883  }
884  }
886  if (!stream->put64bitsLE((U8*)&(header->max_x)))
887  {
888  fprintf(stderr,"ERROR: updating header->max_x\n");
889  return FALSE;
890  }
891  if (!stream->put64bitsLE((U8*)&(header->min_x)))
892  {
893  fprintf(stderr,"ERROR: updating header->min_x\n");
894  return FALSE;
895  }
896  if (!stream->put64bitsLE((U8*)&(header->max_y)))
897  {
898  fprintf(stderr,"ERROR: updating header->max_y\n");
899  return FALSE;
900  }
901  if (!stream->put64bitsLE((U8*)&(header->min_y)))
902  {
903  fprintf(stderr,"ERROR: updating header->min_y\n");
904  return FALSE;
905  }
906  if (!stream->put64bitsLE((U8*)&(header->max_z)))
907  {
908  fprintf(stderr,"ERROR: updating header->max_z\n");
909  return FALSE;
910  }
911  if (!stream->put64bitsLE((U8*)&(header->min_z)))
912  {
913  fprintf(stderr,"ERROR: updating header->min_z\n");
914  return FALSE;
915  }
916  }
917  if (update_extra_bytes)
918  {
919  if (header->number_extra_attributes)
920  {
921  I64 start = header_start_position + header->header_size;
922  for (i = 0; i < (I32)header->number_of_variable_length_records; i++)
923  {
924  start += 54;
925  if (header->vlrs[i].data == (char*)header->extra_attributes)
926  {
927  break;
928  }
929  else
930  {
931  start += header->vlrs[i].record_length_after_header;
932  }
933  }
934  stream->seek(start);
935  if (!stream->putBytes((U8*)header->vlrs[i].data, header->vlrs[i].record_length_after_header))
936  {
937  fprintf(stderr,"ERROR: writing %d bytes of data from header->vlrs[%d].data\n", header->vlrs[i].record_length_after_header, i);
938  return FALSE;
939  }
940  }
941  }
942  stream->seekEnd();
943  return TRUE;
944 }
945 
947 {
948  I64 bytes = 0;
949 
950  if (p_count != npoints)
951  {
952 #ifdef _WIN32
953  fprintf(stderr,"WARNING: written %I64d points but expected %I64d points\n", p_count, npoints);
954 #else
955  fprintf(stderr,"WARNING: written %lld points but expected %lld points\n", p_count, npoints);
956 #endif
957  }
958 
959  if (writer)
960  {
961  writer->done();
962  delete writer;
963  writer = 0;
964  }
965 
966  if (stream)
967  {
968  if (update_header && p_count != npoints)
969  {
970  if (!stream->isSeekable())
971  {
972 #ifdef _WIN32
973  fprintf(stderr, "ERROR: stream not seekable. cannot update header from %I64d to %I64d points.\n", npoints, p_count);
974 #else
975  fprintf(stderr, "ERROR: stream not seekable. cannot update header from %lld to %lld points.\n", npoints, p_count);
976 #endif
977  }
978  else
979  {
982  stream->seekEnd();
983  }
984  }
985  bytes = stream->tell() - header_start_position;
986  delete stream;
987  stream = 0;
988  }
989 
990  if (file)
991  {
992  fclose(file);
993  file = 0;
994  }
995 
996  npoints = p_count;
997  p_count = 0;
998 
999  return bytes;
1000 }
1001 
1003 {
1004  file = 0;
1005  stream = 0;
1006  writer = 0;
1007 }
1008 
1010 {
1011  if (writer || stream) close();
1012 }
LASquantizer::y_offset
F64 y_offset
Definition: lasdefinitions.hpp:96
LASitem::version
unsigned short version
Definition: laszip.hpp:75
LASheader::start_of_first_extended_variable_length_record
U64 start_of_first_extended_variable_length_record
Definition: lasdefinitions.hpp:986
LASheader
Definition: lasdefinitions.hpp:952
LASvlr_lastiling::level
U32 level
Definition: lasdefinitions.hpp:941
LASheader::system_identifier
I8 system_identifier[32]
Definition: lasdefinitions.hpp:964
LASzip::num_items
unsigned short num_items
Definition: laszip.hpp:120
LASheader::min_y
F64 min_y
Definition: lasdefinitions.hpp:978
LASheader::number_of_points_by_return
U32 number_of_points_by_return[5]
Definition: lasdefinitions.hpp:974
LASzip::setup
bool setup(unsigned short *num_items, LASitem **items, const unsigned char point_type, const unsigned short point_size, const unsigned short compressor=LASZIP_COMPRESSOR_NONE)
Definition: laszip.cpp:320
LASheader::user_data_in_header
I8 * user_data_in_header
Definition: lasdefinitions.hpp:992
LASvlr::reserved
U16 reserved
Definition: lasdefinitions.hpp:884
LASquantizer::get_y
F64 get_y(const I32 y) const
Definition: lasdefinitions.hpp:100
LASwriterLAS::~LASwriterLAS
~LASwriterLAS()
Definition: laswriter_las.cpp:1009
LASwriterLAS::refile
BOOL refile(FILE *file)
Definition: laswriter_las.cpp:46
LASZIP_COMPRESSOR_NONE
#define LASZIP_COMPRESSOR_NONE
Definition: laszip.hpp:53
LASpoint
Definition: lasdefinitions.hpp:472
ByteStreamOut::put16bitsLE
virtual BOOL put16bitsLE(const U8 *bytes)=0
LASinventory::active
BOOL active() const
Definition: lasutility.hpp:39
LASheader::generating_software
I8 generating_software[32]
Definition: lasdefinitions.hpp:965
laswritepoint.hpp
LASheader::header_size
U16 header_size
Definition: lasdefinitions.hpp:968
I64
long long I64
Definition: mydefs.hpp:48
LASwriterLAS::update_header
BOOL update_header(const LASheader *header, BOOL use_inventory=TRUE, BOOL update_extra_bytes=FALSE)
Definition: laswriter_las.cpp:794
LASquantizer::get_z
F64 get_z(const I32 z) const
Definition: lasdefinitions.hpp:101
F64
double F64
Definition: mydefs.hpp:52
LASzip::version_revision
unsigned short version_revision
Definition: laszip.hpp:115
LASwriter::p_count
I64 p_count
Definition: laswriter.hpp:52
LASzip
Definition: laszip.hpp:80
LASinventory::raw_max_x
I32 raw_max_x
Definition: lasutility.hpp:42
LASquantizer::x_scale_factor
F64 x_scale_factor
Definition: lasdefinitions.hpp:92
LASwritePoint::write
BOOL write(const U8 *const *point)
Definition: laswritepoint.cpp:243
I32
int I32
Definition: mydefs.hpp:35
LASheader::number_of_extended_variable_length_records
U32 number_of_extended_variable_length_records
Definition: lasdefinitions.hpp:987
TRUE
#define TRUE
Definition: mydefs.hpp:137
LASwriterLAS::writer
LASwritePoint * writer
Definition: laswriter_las.hpp:78
LASheader::project_ID_GUID_data_3
U16 project_ID_GUID_data_3
Definition: lasdefinitions.hpp:960
LASwriterLAS::LASwriterLAS
LASwriterLAS()
Definition: laswriter_las.cpp:1002
LASzip::items
LASitem * items
Definition: laszip.hpp:121
LASzip::is_standard
bool is_standard(const unsigned short num_items, const LASitem *items, unsigned char *point_type=0, unsigned short *record_length=0)
Definition: laszip.cpp:511
LASheader::extended_number_of_points_by_return
U64 extended_number_of_points_by_return[15]
Definition: lasdefinitions.hpp:989
ByteStreamOutFile
Definition: bytestreamout_file.hpp:43
LASwriter::inventory
LASinventory inventory
Definition: laswriter.hpp:53
LASheader::check
BOOL check() const
Definition: lasdefinitions.hpp:1117
LASwritePoint::chunk
BOOL chunk()
Definition: laswritepoint.cpp:276
LASheader::number_of_variable_length_records
U32 number_of_variable_length_records
Definition: lasdefinitions.hpp:970
LASquantizer::x_offset
F64 x_offset
Definition: lasdefinitions.hpp:95
LASheader::project_ID_GUID_data_4
U8 project_ID_GUID_data_4[8]
Definition: lasdefinitions.hpp:961
LASheader::number_of_point_records
U32 number_of_point_records
Definition: lasdefinitions.hpp:973
NULL
#define NULL
Definition: mydefs.hpp:141
ByteStreamOut::put32bitsLE
virtual BOOL put32bitsLE(const U8 *bytes)=0
LASattributer::number_extra_attributes
I32 number_extra_attributes
Definition: lasdefinitions.hpp:308
ByteStreamOut::put64bitsLE
virtual BOOL put64bitsLE(const U8 *bytes)=0
ByteStreamOut::tell
virtual I64 tell() const =0
LASvlr::record_id
U16 record_id
Definition: lasdefinitions.hpp:886
ByteStreamOut::putByte
virtual BOOL putByte(U8 byte)=0
bytestreamout_ostream.hpp
LASzip::chunk_size
unsigned int chunk_size
Definition: laszip.hpp:117
LASvlr::description
I8 description[32]
Definition: lasdefinitions.hpp:888
LASzip::version_major
unsigned char version_major
Definition: laszip.hpp:113
LASpoint::num_items
U16 num_items
Definition: lasdefinitions.hpp:525
LASzip::request_version
bool request_version(const unsigned short requested_version)
Definition: laszip.cpp:473
LASheader::start_of_waveform_data_packet_record
U64 start_of_waveform_data_packet_record
Definition: lasdefinitions.hpp:983
LASwriterLAS::close
I64 close(BOOL update_npoints=true)
Definition: laswriter_las.cpp:946
ByteStreamOut
Definition: bytestreamout.hpp:36
LASzip::compressor
unsigned short compressor
Definition: laszip.hpp:111
LASheader::point_data_format
U8 point_data_format
Definition: lasdefinitions.hpp:971
LASzip::num_points
SIGNED_INT64 num_points
Definition: laszip.hpp:118
LASinventory::raw_max_z
I32 raw_max_z
Definition: lasutility.hpp:46
LASzip::set_chunk_size
bool set_chunk_size(const unsigned int chunk_size)
Definition: laszip.cpp:462
LASheader::global_encoding
U16 global_encoding
Definition: lasdefinitions.hpp:957
LASpoint::items
LASitem * items
Definition: lasdefinitions.hpp:526
LASheader::user_data_after_header
I8 * user_data_after_header
Definition: lasdefinitions.hpp:1006
LASheader::extended_number_of_point_records
U64 extended_number_of_point_records
Definition: lasdefinitions.hpp:988
LASheader::file_creation_year
U16 file_creation_year
Definition: lasdefinitions.hpp:967
LASheader::file_signature
I8 file_signature[4]
Definition: lasdefinitions.hpp:955
LASinventory::raw_min_z
I32 raw_min_z
Definition: lasutility.hpp:47
LASvlr_lastiling::max_y
F32 max_y
Definition: lasdefinitions.hpp:949
LASzip::version_minor
unsigned char version_minor
Definition: laszip.hpp:114
LASvlr_lastiling::min_x
F32 min_x
Definition: lasdefinitions.hpp:946
LASheader::version_major
U8 version_major
Definition: lasdefinitions.hpp:962
LASheader::project_ID_GUID_data_1
U32 project_ID_GUID_data_1
Definition: lasdefinitions.hpp:958
LASvlr_lastiling::min_y
F32 min_y
Definition: lasdefinitions.hpp:948
LASheader::max_x
F64 max_x
Definition: lasdefinitions.hpp:975
LASitem::size
unsigned short size
Definition: laszip.hpp:74
ByteStreamOutOstreamLE
Definition: bytestreamout_ostream.hpp:66
U16
unsigned short U16
Definition: mydefs.hpp:40
LASwriterLAS::write_point
BOOL write_point(const LASpoint *point)
Definition: laswriter_las.cpp:783
LASquantizer::z_offset
F64 z_offset
Definition: lasdefinitions.hpp:97
LASwriterLAS::chunk
BOOL chunk()
Definition: laswriter_las.cpp:789
LASwriter::quantizer
LASquantizer quantizer
Definition: laswriter.hpp:50
ByteStreamOut::seek
virtual BOOL seek(const I64 position)=0
ByteStreamOutOstreamBE
Definition: bytestreamout_ostream.hpp:86
U8
unsigned char U8
Definition: mydefs.hpp:41
BOOL
int BOOL
Definition: mydefs.hpp:57
U64
unsigned long long U64
Definition: mydefs.hpp:47
LASheader::version_minor
U8 version_minor
Definition: lasdefinitions.hpp:963
ByteStreamOut::isSeekable
virtual BOOL isSeekable() const =0
LASheader::user_data_after_header_size
U32 user_data_after_header_size
Definition: lasdefinitions.hpp:1005
bytestreamout_file.hpp
LASheader::laszip
LASzip * laszip
Definition: lasdefinitions.hpp:1002
LASwritePoint
Definition: laswritepoint.hpp:48
FALSE
#define FALSE
Definition: mydefs.hpp:133
file
FILE * file
Definition: arithmeticencoder.cpp:77
ByteStreamOutFileBE
Definition: bytestreamout_file.hpp:87
LASvlr::record_length_after_header
U16 record_length_after_header
Definition: lasdefinitions.hpp:887
LASheader::max_y
F64 max_y
Definition: lasdefinitions.hpp:977
LASvlr_lastiling::implicit_levels
U32 implicit_levels
Definition: lasdefinitions.hpp:943
LASheader::project_ID_GUID_data_2
U16 project_ID_GUID_data_2
Definition: lasdefinitions.hpp:959
LASwritePoint::done
BOOL done()
Definition: laswritepoint.cpp:289
LAS_TOOLS_VERSION
#define LAS_TOOLS_VERSION
Definition: lasdefinitions.hpp:47
LASwriter::npoints
I64 npoints
Definition: laswriter.hpp:51
LASheader::min_x
F64 min_x
Definition: lasdefinitions.hpp:976
bytestreamout_nil.hpp
LASpoint::init
BOOL init(const LASquantizer *quantizer, const U8 point_type, const U16 point_size, const LASattributer *attributer=0)
Definition: lasdefinitions.hpp:595
LASheader::user_data_in_header_size
U32 user_data_in_header_size
Definition: lasdefinitions.hpp:991
LASwritePoint::setup
BOOL setup(const U32 num_items, const LASitem *items, const LASzip *laszip=0)
Definition: laswritepoint.cpp:61
LASitem::type
enum LASitem::Type type
IS_LITTLE_ENDIAN
BOOL IS_LITTLE_ENDIAN()
Definition: mydefs.hpp:144
LASheader::vlr_lastiling
LASvlr_lastiling * vlr_lastiling
Definition: lasdefinitions.hpp:1003
LASinventory::number_of_point_records
U32 number_of_point_records
Definition: lasutility.hpp:39
U32
unsigned int U32
Definition: mydefs.hpp:39
LASheader::vlrs
LASvlr * vlrs
Definition: lasdefinitions.hpp:994
LASwriterLAS::open
BOOL open(const LASheader *header, U32 compressor=LASZIP_COMPRESSOR_NONE, I32 requested_version=0, I32 chunk_size=50000)
Definition: laswriter_las.cpp:53
LASzip::num_bytes
SIGNED_INT64 num_bytes
Definition: laszip.hpp:119
LASheader::file_creation_day
U16 file_creation_day
Definition: lasdefinitions.hpp:966
LASquantizer::get_x
F64 get_x(const I32 x) const
Definition: lasdefinitions.hpp:99
LASwriterLAS::file
FILE * file
Definition: laswriter_las.hpp:79
LASattributer::extra_attributes
LASattribute * extra_attributes
Definition: lasdefinitions.hpp:309
LASheader::max_z
F64 max_z
Definition: lasdefinitions.hpp:979
LASvlr_lastiling::level_index
U32 level_index
Definition: lasdefinitions.hpp:942
laswriter_las.hpp
LASpoint::point
U8 ** point
Definition: lasdefinitions.hpp:513
LASwritePoint::init
BOOL init(ByteStreamOut *outstream)
Definition: laswritepoint.cpp:204
LASvlr::data
I8 * data
Definition: lasdefinitions.hpp:889
LASheader::point_data_record_length
U16 point_data_record_length
Definition: lasdefinitions.hpp:972
LASheader::offset_to_point_data
U32 offset_to_point_data
Definition: lasdefinitions.hpp:969
LASzip::coder
unsigned short coder
Definition: laszip.hpp:112
ByteStreamOutNil
Definition: bytestreamout_nil.hpp:38
LASvlr::user_id
I8 user_id[16]
Definition: lasdefinitions.hpp:885
LASvlr_lastiling::max_x
F32 max_x
Definition: lasdefinitions.hpp:947
LASwriterLAS::header_start_position
I64 header_start_position
Definition: laswriter_las.hpp:80
LASquantizer::y_scale_factor
F64 y_scale_factor
Definition: lasdefinitions.hpp:93
ByteStreamOut::seekEnd
virtual BOOL seekEnd()=0
ByteStreamOut::putBytes
virtual BOOL putBytes(const U8 *bytes, U32 num_bytes)=0
LASinventory::raw_max_y
I32 raw_max_y
Definition: lasutility.hpp:44
LASwriterLAS::stream
ByteStreamOut * stream
Definition: laswriter_las.hpp:77
LASquantizer::z_scale_factor
F64 z_scale_factor
Definition: lasdefinitions.hpp:94
LASheader::min_z
F64 min_z
Definition: lasdefinitions.hpp:980
LASzip::options
unsigned int options
Definition: laszip.hpp:116
LASheader::file_source_id
U16 file_source_id
Definition: lasdefinitions.hpp:956
LASinventory::raw_min_x
I32 raw_min_x
Definition: lasutility.hpp:43
ByteStreamOutFileLE
Definition: bytestreamout_file.hpp:67
LASinventory::raw_min_y
I32 raw_min_y
Definition: lasutility.hpp:45
LASinventory::number_of_points_by_return
U32 number_of_points_by_return[8]
Definition: lasutility.hpp:41


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Wed Mar 2 2022 00:37:23