1 // 2 // (C) Copyright 2010 Michael P. Gerlek (mpg@flaxen.com) 3 // Distributed under the BSD License 4 // (See accompanying file LICENSE.txt or copy at 5 // http://www.opensource.org/licenses/bsd-license.php) 6 // 7 8 #ifdef HAVE_LASZIP 9 10 #include <liblas/liblas.hpp> 11 #include <tut/tut.hpp> 12 #include <cstdio> 13 #include <bitset> 14 #include <fstream> 15 #include <string> 16 #include "liblas_test.hpp" 17 #include "common.hpp" 18 19 namespace tut 20 { 21 struct zipwriter_data 22 { 23 std::string file_laz; 24 std::string header_10; 25 std::string header_10_vlr; 26 std::string header_12; 27 std::string header_12_vlr; 28 std::string header_10_compressed; 29 std::string header_10_compressed_vlr; 30 std::string header_12_compressed; 31 std::string header_12_compressed_vlr; 32 std::string header_12_padded; 33 std::string header_12_too_small_pad; 34 zipwriter_datatut::zipwriter_data35 zipwriter_data() : 36 file_laz(g_test_data_path + "//tmp.laz"), 37 header_10(g_test_data_path + "//header-1.0-test.las"), 38 header_10_vlr(g_test_data_path + "//header-1.0-vlr-test.las"), 39 header_12(g_test_data_path + "//header-1.2-test.las"), 40 header_12_vlr(g_test_data_path + "//header-1.2-vlr-test.las"), 41 header_10_compressed(g_test_data_path + "//header-1.0-compressed-test.laz"), 42 header_10_compressed_vlr(g_test_data_path + "//header-1.0-compressed-test.laz"), 43 header_12_compressed(g_test_data_path + "//header-1.2-compressed-test.laz"), 44 header_12_compressed_vlr(g_test_data_path + "//header-1.2-compressed-test.laz"), 45 header_12_padded(g_test_data_path + "//header-1.2-padded.laz"), 46 header_12_too_small_pad(g_test_data_path + "//header-1.2-too-small-pad.laz") 47 {} 48 ~zipwriter_datatut::zipwriter_data49 ~zipwriter_data() 50 { 51 cleanup(file_laz); 52 cleanup(header_10); 53 cleanup(header_10_vlr); 54 cleanup(header_12); 55 cleanup(header_12_vlr); 56 cleanup(header_10_compressed); 57 cleanup(header_10_compressed_vlr); 58 cleanup(header_12_compressed); 59 cleanup(header_12_compressed_vlr); 60 cleanup(header_12_padded); 61 cleanup(header_12_too_small_pad); 62 63 } 64 cleanuptut::zipwriter_data65 void cleanup(std::string const& input) 66 { 67 const int ret = std::remove(input.c_str()); 68 if (0 != ret) 69 { 70 ; // ignore, file may not exist 71 } 72 } 73 setuptut::zipwriter_data74 void setup( std::string const& input, 75 liblas::Header const& header) 76 { 77 78 std::ofstream ofs; 79 ofs.open(input.c_str(), std::ios::out | std::ios::binary); 80 81 liblas::Writer writer(ofs, header); 82 83 liblas::Point point(&writer.GetHeader()); 84 85 // Write 1st point 86 point.SetCoordinates(10, 20, 30); 87 point.SetIntensity(5); 88 point.SetReturnNumber(1); 89 point.SetNumberOfReturns(1); 90 point.SetScanDirection(1); 91 point.SetFlightLineEdge(1); 92 point.SetClassification(7); 93 point.SetScanAngleRank(90); 94 point.SetUserData(0); 95 point.SetPointSourceID(1); 96 97 writer.WritePoint(point); 98 99 // write 2nd point 100 point.SetCoordinates(40, 50, 60); 101 point.SetPointSourceID(2); 102 writer.WritePoint(point); 103 104 // write 3rd point 105 point.SetCoordinates(70, 80, 90); 106 point.SetPointSourceID(3); 107 writer.WritePoint(point); 108 109 } 110 FetchHeadertut::zipwriter_data111 liblas::Header FetchHeader(std::string input) 112 { 113 std::ifstream ifs; 114 ifs.open(input.c_str(), std::ios::in | std::ios::binary); 115 ensure(ifs.is_open()); 116 117 liblas::ReaderFactory factory; 118 liblas::Reader reader = factory.CreateWithStream(ifs); 119 return reader.GetHeader(); 120 } 121 ConstructVLRtut::zipwriter_data122 liblas::VariableRecord ConstructVLR() 123 { 124 liblas::VariableRecord r; 125 126 std::vector<boost::uint8_t> vdata; 127 vdata.resize(256); 128 for(int i=0; i < 256; i++) 129 { 130 vdata[i] = (boost::uint8_t)i; 131 } 132 r.SetReserved(0xAABB); 133 r.SetUserId("HOBU"); 134 r.SetRecordId(1234); 135 r.SetDescription("some lovely text"); 136 r.SetData(vdata); 137 138 r.SetRecordLength((boost::uint16_t)vdata.size()); 139 return r; 140 } 141 }; 142 143 typedef test_group<zipwriter_data> tg; 144 typedef tg::object to; 145 146 tg test_group_zipwriter("liblas::ZipWriter"); 147 148 // Test ability to make a compressed header 149 template<> 150 template<> test()151 void to::test<1>() 152 { 153 // Create new LAS file using default header block 154 { 155 std::ofstream ofs; 156 ofs.open(file_laz.c_str(), std::ios::out | std::ios::binary); 157 158 // LAS 1.2, Point Format 0 159 liblas::Header header; 160 ensure_equals(header.Compressed(), false); 161 header.SetCompressed(true); 162 ensure_equals(header.Compressed(), true); 163 164 liblas::Writer writer(ofs, header); 165 } 166 167 // Read previously created LAS file and check its header block, laszip VLR 168 { 169 std::ifstream ifs; 170 ifs.open(file_laz.c_str(), std::ios::in | std::ios::binary); 171 ensure(ifs.is_open()); 172 173 liblas::ReaderFactory factory; 174 liblas::Reader reader = factory.CreateWithStream(ifs); 175 176 ensure_equals(reader.GetHeader().Compressed(), true); 177 178 test_laszip_vlr(reader.GetHeader()); 179 } 180 181 return; 182 } 183 184 // Test ability to write a few points, using the writer factory 185 template<> 186 template<> test()187 void to::test<2>() 188 { 189 { 190 std::ofstream ofs; 191 ofs.open(file_laz.c_str(), std::ios::out | std::ios::binary); 192 193 // LAS 1.1, Point Format 0 194 liblas::Header header; 195 header.SetCompressed(true); 196 197 liblas::Writer writer(ofs, header); 198 199 liblas::Point point(&writer.GetHeader()); 200 201 // Write 1st point 202 point.SetCoordinates(10, 20, 30); 203 point.SetIntensity(5); 204 point.SetReturnNumber(1); 205 point.SetNumberOfReturns(1); 206 point.SetScanDirection(1); 207 point.SetFlightLineEdge(1); 208 point.SetClassification(7); 209 point.SetScanAngleRank(90); 210 point.SetUserData(0); 211 point.SetPointSourceID(1); 212 213 writer.WritePoint(point); 214 215 // write 2nd point 216 point.SetCoordinates(40, 50, 60); 217 point.SetPointSourceID(2); 218 writer.WritePoint(point); 219 220 // write 3rd point 221 point.SetCoordinates(70, 80, 90); 222 point.SetPointSourceID(3); 223 writer.WritePoint(point); 224 } 225 226 // Read previously create LAS file with 3 point records 227 { 228 std::ifstream ifs; 229 ifs.open(file_laz.c_str(), std::ios::in | std::ios::binary); 230 ensure(ifs.is_open()); 231 232 liblas::ReaderFactory factory; 233 liblas::Reader reader = factory.CreateWithStream(ifs); 234 235 ensure_equals(reader.GetHeader().Compressed(), true); 236 237 liblas::Point point(&reader.GetHeader()); // reusable cache 238 239 // read 1st point 240 bool ok = reader.ReadNextPoint(); 241 ensure_equals(ok, true); 242 point = reader.GetPoint(); 243 244 ensure_distance(point.GetX(), 10.0, 0.1); 245 ensure_distance(point.GetY(), 20.0, 0.1); 246 ensure_distance(point.GetZ(), 30.0, 0.1); 247 ensure_equals(point.GetIntensity(), 5); 248 ensure_equals(point.GetReturnNumber(), 1); 249 ensure_equals(point.GetNumberOfReturns(), 1); 250 ensure_equals(point.GetScanDirection(), 1); 251 ensure_equals(point.GetFlightLineEdge(), 1); 252 ensure_equals(point.GetScanAngleRank(), 90); 253 ensure_equals(point.GetUserData(), 0); 254 ensure_equals(point.GetPointSourceID(), 1); 255 256 typedef liblas::Classification::bitset_type bitset_type; 257 ensure_equals(bitset_type(point.GetClassification()), bitset_type(7)); 258 259 // read 2nd point 260 ok = reader.ReadNextPoint(); 261 ensure_equals(ok, true); 262 point = reader.GetPoint(); 263 264 ensure_distance(point.GetX(), 40.0, 0.1); 265 ensure_distance(point.GetY(), 50.0, 0.1); 266 ensure_distance(point.GetZ(), 60.0, 0.1); 267 ensure_equals(point.GetIntensity(), 5); 268 ensure_equals(point.GetReturnNumber(), 1); 269 ensure_equals(point.GetNumberOfReturns(), 1); 270 ensure_equals(point.GetScanDirection(), 1); 271 ensure_equals(point.GetFlightLineEdge(), 1); 272 ensure_equals(point.GetScanAngleRank(), 90); 273 ensure_equals(point.GetUserData(), 0); 274 ensure_equals(point.GetPointSourceID(), 2); 275 276 // read 3rd point 277 ok = reader.ReadNextPoint(); 278 ensure_equals(ok, true); 279 point = reader.GetPoint(); 280 281 ensure_distance(point.GetX(), 70.0, 0.1); 282 ensure_distance(point.GetY(), 80.0, 0.1); 283 ensure_distance(point.GetZ(), 90.0, 0.1); 284 ensure_equals(point.GetIntensity(), 5); 285 ensure_equals(point.GetReturnNumber(), 1); 286 ensure_equals(point.GetNumberOfReturns(), 1); 287 ensure_equals(point.GetScanDirection(), 1); 288 ensure_equals(point.GetFlightLineEdge(), 1); 289 ensure_equals(point.GetScanAngleRank(), 90); 290 ensure_equals(point.GetUserData(), 0); 291 ensure_equals(point.GetPointSourceID(), 3); 292 293 typedef liblas::Classification::bitset_type bitset_type; 294 ensure_equals(bitset_type(point.GetClassification()), bitset_type(7)); 295 296 return; 297 } 298 } 299 300 // Test header integrity 301 template<> 302 template<> test()303 void to::test<3>() 304 { 305 306 { 307 liblas::Header header; 308 309 header.SetVersionMinor(0); 310 header.SetHeaderPadding(0); 311 header.SetCompressed(false); 312 313 setup(header_10, header); 314 } 315 316 { 317 liblas::Header header = FetchHeader(header_10); 318 319 ensure_equals("1.0 no-vlr iscompressed?", header.Compressed(), false); 320 321 // compression is going to add the LASzip VLR 322 ensure_equals("1.0 no-vlr data offset", header.GetDataOffset(), (boost::uint32_t)229); 323 ensure_equals("1.0 no-vlr header padding", header.GetHeaderPadding(), (boost::uint32_t)2); 324 325 } 326 327 { 328 liblas::Header header; 329 330 header.SetVersionMinor(0); 331 header.SetHeaderPadding(0); 332 header.SetCompressed(false); 333 liblas::VariableRecord v = ConstructVLR(); 334 header.AddVLR(v); 335 336 setup(header_10_vlr, header); 337 } 338 339 { 340 liblas::Header header = FetchHeader(header_10_vlr); 341 342 ensure_equals("1.0 vlr iscompressed?", header.Compressed(), false); 343 344 // compression is going to add the LASzip VLR 345 ensure_equals("1.0 vlr data offset", header.GetDataOffset(), (boost::uint32_t)539); 346 ensure_equals("1.0 vlr header padding", header.GetHeaderPadding(), (boost::uint32_t)2); 347 348 } 349 350 { 351 liblas::Header header; 352 353 header.SetVersionMinor(2); 354 header.SetHeaderPadding(0); 355 header.SetCompressed(false); 356 357 setup(header_12, header); 358 } 359 360 { 361 liblas::Header header = FetchHeader(header_12); 362 363 ensure_equals("1.2 no-vlr iscompressed?", header.Compressed(), false); 364 365 // compression is going to add the LASzip VLR 366 ensure_equals("1.2 no-vlr data offset", header.GetDataOffset(), (boost::uint32_t)227); 367 ensure_equals("1.2 no-vlr header padding", header.GetHeaderPadding(), (boost::uint32_t)0); 368 369 } 370 371 { 372 liblas::Header header; 373 374 header.SetVersionMinor(2); 375 header.SetHeaderPadding(0); 376 header.SetCompressed(false); 377 liblas::VariableRecord v = ConstructVLR(); 378 header.AddVLR(v); 379 380 setup(header_12_vlr, header); 381 } 382 383 { 384 liblas::Header header = FetchHeader(header_12_vlr); 385 386 ensure_equals("1.2 vlr iscompressed?", header.Compressed(), false); 387 388 // compression is going to add the LASzip VLR 389 ensure_equals("1.2 vlr data offset", header.GetDataOffset(), (boost::uint32_t)537); 390 ensure_equals("1.2 vlr header padding", header.GetHeaderPadding(), (boost::uint32_t)0); 391 392 } 393 394 { 395 liblas::Header header; 396 397 header.SetVersionMinor(0); 398 header.SetHeaderPadding(0); 399 header.SetCompressed(true); 400 401 setup(header_10_compressed, header); 402 } 403 404 { 405 liblas::Header header = FetchHeader(header_10_compressed); 406 407 ensure_equals("1.0 no-vlr compressed iscompressed?", header.Compressed(), true); 408 409 // compression is going to add the LASzip VLR 410 ensure_equals("1.0 no-vlr compressed data offset", header.GetDataOffset(), (boost::uint32_t)335); 411 ensure_equals("1.0 no-vlr compressed header padding", header.GetHeaderPadding(), (boost::uint32_t)2); 412 413 } 414 415 { 416 liblas::Header header; 417 418 header.SetVersionMinor(2); 419 header.SetHeaderPadding(0); 420 header.SetCompressed(true); 421 422 setup(header_12_compressed, header); 423 } 424 425 { 426 liblas::Header header = FetchHeader(header_12_compressed); 427 428 ensure_equals("1.2 no-vlr compressed iscompressed?", header.Compressed(), true); 429 430 // compression is going to add the LASzip VLR 431 ensure_equals("1.2 no-vlr compressed data offset", header.GetDataOffset(), (boost::uint32_t)333); 432 ensure_equals("1.2 no-vlr compressed header padding", header.GetHeaderPadding(), (boost::uint32_t)0); 433 434 } 435 436 { 437 liblas::Header header; 438 439 header.SetVersionMinor(2); 440 header.SetHeaderPadding(0); 441 header.SetCompressed(true); 442 liblas::VariableRecord v = ConstructVLR(); 443 header.AddVLR(v); 444 445 setup(header_12_compressed_vlr, header); 446 } 447 448 { 449 liblas::Header header = FetchHeader(header_12_compressed_vlr); 450 451 ensure_equals("1.2 vlr compressed iscompressed?", header.Compressed(), true); 452 453 // compression is going to add the LASzip VLR 454 ensure_equals("1.2 vlr compressed data offset", header.GetDataOffset(), (boost::uint32_t)643); 455 ensure_equals("1.2 vlr compressed header padding", header.GetHeaderPadding(), (boost::uint32_t)0); 456 457 } 458 459 { 460 liblas::Header header; 461 462 header.SetVersionMinor(2); 463 header.SetHeaderPadding(0); 464 header.SetCompressed(true); 465 header.SetDataOffset(1024); 466 liblas::VariableRecord v = ConstructVLR(); 467 header.AddVLR(v); 468 469 setup(header_12_padded, header); 470 } 471 472 { 473 liblas::Header header = FetchHeader(header_12_padded); 474 475 ensure_equals("1.2 header_12_padded iscompressed?", header.Compressed(), true); 476 477 // compression is going to add the LASzip VLR 478 ensure_equals("1.2 header_12_padded data offset", header.GetDataOffset(), (boost::uint32_t)1024); 479 ensure_equals("1.2 header_12_padded header padding", header.GetHeaderPadding(), (boost::uint32_t)381); 480 481 } 482 483 { 484 liblas::Header header; 485 486 header.SetVersionMinor(2); 487 header.SetHeaderPadding(0); 488 header.SetCompressed(true); 489 header.SetDataOffset(440); 490 liblas::VariableRecord v = ConstructVLR(); 491 header.AddVLR(v); 492 493 setup(header_12_too_small_pad, header); 494 } 495 496 { 497 liblas::Header header = FetchHeader(header_12_too_small_pad); 498 499 ensure_equals("1.2 header_12_too_small_pad iscompressed?", header.Compressed(), true); 500 501 // compression is going to add the LASzip VLR 502 ensure_equals("1.2 header_12_too_small_pad data offset", header.GetDataOffset(), (boost::uint32_t)643); 503 ensure_equals("1.2 header_12_too_small_pad header padding", header.GetHeaderPadding(), (boost::uint32_t)0); 504 505 } 506 } 507 } 508 509 #endif // HAVE_LASZIP 510