示例#1
0
BOOL LASwriterLAS::open(ByteStreamOut* stream, const LASheader* header, U32 compressor, I32 requested_version, I32 chunk_size)
{
  U32 i, j;

  if (stream == 0)
  {
    fprintf(stderr,"ERROR: ByteStreamOut pointer is zero\n");
    return FALSE;
  }
  this->stream = stream;

  if (header == 0)
  {
    fprintf(stderr,"ERROR: LASheader pointer is zero\n");
    return FALSE;
  }

  // check header contents

  if (!header->check()) return FALSE;

  // copy scale_and_offset
  quantizer.x_scale_factor = header->x_scale_factor;
  quantizer.y_scale_factor = header->y_scale_factor;
  quantizer.z_scale_factor = header->z_scale_factor;
  quantizer.x_offset = header->x_offset;
  quantizer.y_offset = header->y_offset;
  quantizer.z_offset = header->z_offset;

  // check if the requested point type is supported

  LASpoint point;
  U8 point_data_format;
  U16 point_data_record_length;
  BOOL point_is_standard = TRUE;

  if (header->laszip)
  {
    if (!point.init(&quantizer, header->laszip->num_items, header->laszip->items, header)) return FALSE;
    point_is_standard = header->laszip->is_standard(&point_data_format, &point_data_record_length);
  }
  else
  {
    if (!point.init(&quantizer, header->point_data_format, header->point_data_record_length, header)) return FALSE;
    point_data_format = header->point_data_format;
    point_data_record_length = header->point_data_record_length;
  }

  // do we need a LASzip VLR (because we compress or use non-standard points?) 

  LASzip* laszip = 0;
  U32 laszip_vlr_data_size = 0;
  if (compressor || point_is_standard == FALSE)
  {
    laszip = new LASzip();
    laszip->setup(point.num_items, point.items, compressor);
    if (chunk_size > -1) laszip->set_chunk_size((U32)chunk_size);
    if (compressor == LASZIP_COMPRESSOR_NONE) laszip->request_version(0);
    else if (chunk_size == 0) { fprintf(stderr,"ERROR: adaptive chunking is depricated\n"); return FALSE; }
    else if (requested_version) laszip->request_version(requested_version);
    else laszip->request_version(2);
    laszip_vlr_data_size = 34 + 6*laszip->num_items;
  }

  // create and setup the point writer

  writer = new LASwritePoint();
  if (laszip)
  {
    if (!writer->setup(laszip->num_items, laszip->items, laszip))
    {
      fprintf(stderr,"ERROR: point type %d of size %d not supported (with LASzip)\n", header->point_data_format, header->point_data_record_length);
      return FALSE;
    }
  }
  else
  {
    if (!writer->setup(point.num_items, point.items))
    {
      fprintf(stderr,"ERROR: point type %d of size %d not supported\n", header->point_data_format, header->point_data_record_length);
      return FALSE;
    }
  }

  // save the position where we start writing the header

  header_start_position = stream->tell();

  // write header variable after variable (to avoid alignment issues)

  if (!stream->putBytes((U8*)&(header->file_signature), 4))
  {
    fprintf(stderr,"ERROR: writing header->file_signature\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->file_source_ID)))
  {
    fprintf(stderr,"ERROR: writing header->file_source_ID\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->global_encoding)))
  {
    fprintf(stderr,"ERROR: writing header->global_encoding\n");
    return FALSE;
  }
  if (!stream->put32bitsLE((U8*)&(header->project_ID_GUID_data_1)))
  {
    fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_1\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->project_ID_GUID_data_2)))
  {
    fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_2\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->project_ID_GUID_data_3)))
  {
    fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_3\n");
    return FALSE;
  }
  if (!stream->putBytes((U8*)header->project_ID_GUID_data_4, 8))
  {
    fprintf(stderr,"ERROR: writing header->project_ID_GUID_data_4\n");
    return FALSE;
  }
  // check version major
  U8 version_major = header->version_major;
  if (header->version_major != 1)
  {
    fprintf(stderr,"WARNING: header->version_major is %d. writing 1 instead.\n", header->version_major);
    version_major = 1;
  }
  if (!stream->putByte(header->version_major))
  {
    fprintf(stderr,"ERROR: writing header->version_major\n");
    return FALSE;
  }
  // check version minor
  U8 version_minor = header->version_minor;
  if (version_minor > 4)
  {
    fprintf(stderr,"WARNING: header->version_minor is %d. writing 4 instead.\n", version_minor);
    version_minor = 4;
  }
  if (!stream->putByte(version_minor))
  {
    fprintf(stderr,"ERROR: writing header->version_minor\n");
    return FALSE;
  }
  if (!stream->putBytes((U8*)header->system_identifier, 32))
  {
    fprintf(stderr,"ERROR: writing header->system_identifier\n");
    return FALSE;
  }
  if (!stream->putBytes((U8*)header->generating_software, 32))
  {
    fprintf(stderr,"ERROR: writing header->generating_software\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->file_creation_day)))
  {
    fprintf(stderr,"ERROR: writing header->file_creation_day\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->file_creation_year)))
  {
    fprintf(stderr,"ERROR: writing header->file_creation_year\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->header_size)))
  {
    fprintf(stderr,"ERROR: writing header->header_size\n");
    return FALSE;
  }
  U32 offset_to_point_data = header->offset_to_point_data;
  if (laszip) offset_to_point_data += (54 + laszip_vlr_data_size);
  if (header->vlr_lastiling) offset_to_point_data += (54 + 28);
  if (header->vlr_lasoriginal) offset_to_point_data += (54 + 176);
  if (!stream->put32bitsLE((U8*)&offset_to_point_data))
  {
    fprintf(stderr,"ERROR: writing header->offset_to_point_data\n");
    return FALSE;
  }
  U32 number_of_variable_length_records = header->number_of_variable_length_records;
  if (laszip) number_of_variable_length_records++;
  if (header->vlr_lastiling) number_of_variable_length_records++;
  if (header->vlr_lasoriginal) number_of_variable_length_records++;
  if (!stream->put32bitsLE((U8*)&(number_of_variable_length_records)))
  {
    fprintf(stderr,"ERROR: writing header->number_of_variable_length_records\n");
    return FALSE;
  }
  if (compressor) point_data_format |= 128;
  if (!stream->putByte(point_data_format))
  {
    fprintf(stderr,"ERROR: writing header->point_data_format\n");
    return FALSE;
  }
  if (!stream->put16bitsLE((U8*)&(header->point_data_record_length)))
  {
    fprintf(stderr,"ERROR: writing header->point_data_record_length\n");
    return FALSE;
  }
  if (!stream->put32bitsLE((U8*)&(header->number_of_point_records)))
  {
    fprintf(stderr,"ERROR: writing header->number_of_point_records\n");
    return FALSE;
  }
  for (i = 0; i < 5; i++)
  {
    if (!stream->put32bitsLE((U8*)&(header->number_of_points_by_return[i])))
    {
      fprintf(stderr,"ERROR: writing header->number_of_points_by_return[%d]\n", i);
      return FALSE;
    }
  }
  if (!stream->put64bitsLE((U8*)&(header->x_scale_factor)))
  {
    fprintf(stderr,"ERROR: writing header->x_scale_factor\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->y_scale_factor)))
  {
    fprintf(stderr,"ERROR: writing header->y_scale_factor\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->z_scale_factor)))
  {
    fprintf(stderr,"ERROR: writing header->z_scale_factor\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->x_offset)))
  {
    fprintf(stderr,"ERROR: writing header->x_offset\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->y_offset)))
  {
    fprintf(stderr,"ERROR: writing header->y_offset\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->z_offset)))
  {
    fprintf(stderr,"ERROR: writing header->z_offset\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->max_x)))
  {
    fprintf(stderr,"ERROR: writing header->max_x\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->min_x)))
  {
    fprintf(stderr,"ERROR: writing header->min_x\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->max_y)))
  {
    fprintf(stderr,"ERROR: writing header->max_y\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->min_y)))
  {
    fprintf(stderr,"ERROR: writing header->min_y\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->max_z)))
  {
    fprintf(stderr,"ERROR: writing header->max_z\n");
    return FALSE;
  }
  if (!stream->put64bitsLE((U8*)&(header->min_z)))
  {
    fprintf(stderr,"ERROR: writing header->min_z\n");
    return FALSE;
  }

  // special handling for LAS 1.3 or higher.
  if (version_minor >= 3)
  {
    U64 start_of_waveform_data_packet_record = header->start_of_waveform_data_packet_record;
    if (start_of_waveform_data_packet_record != 0)
    {
#ifdef _WIN32
      fprintf(stderr,"WARNING: header->start_of_waveform_data_packet_record is %I64d. writing 0 instead.\n", start_of_waveform_data_packet_record);
#else
      fprintf(stderr,"WARNING: header->start_of_waveform_data_packet_record is %lld. writing 0 instead.\n", start_of_waveform_data_packet_record);
#endif
      start_of_waveform_data_packet_record = 0;
    }
    if (!stream->put64bitsLE((U8*)&start_of_waveform_data_packet_record))
    {
      fprintf(stderr,"ERROR: writing start_of_waveform_data_packet_record\n");
      return FALSE;
    }
  }

  // special handling for LAS 1.4 or higher.
  if (version_minor >= 4)
  {
    writing_las_1_4 = TRUE;
    if (header->point_data_format >= 6)
    {
      writing_new_point_type = TRUE;
    }
    else
    {
      writing_new_point_type = FALSE;
    }

    U64 start_of_first_extended_variable_length_record = header->start_of_first_extended_variable_length_record;
    if (start_of_first_extended_variable_length_record != 0)
    {
#ifdef _WIN32
      fprintf(stderr,"WARNING: EVLRs not supported. header->start_of_first_extended_variable_length_record is %I64d. writing 0 instead.\n", start_of_first_extended_variable_length_record);
#else
      fprintf(stderr,"WARNING: EVLRs not supported. header->start_of_first_extended_variable_length_record is %lld. writing 0 instead.\n", start_of_first_extended_variable_length_record);
#endif
      start_of_first_extended_variable_length_record = 0;
    }
    if (!stream->put64bitsLE((U8*)&(start_of_first_extended_variable_length_record)))
    {
      fprintf(stderr,"ERROR: writing header->start_of_first_extended_variable_length_record\n");
      return FALSE;
    }
    U32 number_of_extended_variable_length_records = header->number_of_extended_variable_length_records;
    if (number_of_extended_variable_length_records != 0)
    {
      fprintf(stderr,"WARNING: EVLRs not supported. header->number_of_extended_variable_length_records is %u. writing 0 instead.\n", number_of_extended_variable_length_records);
      number_of_extended_variable_length_records = 0;
    }
    if (!stream->put32bitsLE((U8*)&(number_of_extended_variable_length_records)))
    {
      fprintf(stderr,"ERROR: writing header->number_of_extended_variable_length_records\n");
      return FALSE;
    }
    U64 extended_number_of_point_records;
    if (header->number_of_point_records)
      extended_number_of_point_records = header->number_of_point_records;
    else
      extended_number_of_point_records = header->extended_number_of_point_records;
    if (!stream->put64bitsLE((U8*)&extended_number_of_point_records))
    {
      fprintf(stderr,"ERROR: writing header->extended_number_of_point_records\n");
      return FALSE;
    }
    U64 extended_number_of_points_by_return;
    for (i = 0; i < 15; i++)
    {
      if ((i < 5) && header->number_of_points_by_return[i])
        extended_number_of_points_by_return = header->number_of_points_by_return[i];
      else
        extended_number_of_points_by_return = header->extended_number_of_points_by_return[i];
      if (!stream->put64bitsLE((U8*)&extended_number_of_points_by_return))
      {
        fprintf(stderr,"ERROR: writing header->extended_number_of_points_by_return[%d]\n", i);
        return FALSE;
      }
    }
  }
  else
  {
    writing_las_1_4 = FALSE;
    writing_new_point_type = FALSE;
  }

  // write any number of user-defined bytes that might have been added into the header

  if (header->user_data_in_header_size)
  {
    if (header->user_data_in_header)
    {
      if (!stream->putBytes((U8*)header->user_data_in_header, header->user_data_in_header_size))
      {
        fprintf(stderr,"ERROR: writing %d bytes of data from header->user_data_in_header\n", header->user_data_in_header_size);
        return FALSE;
      }
    }
    else
    {
      fprintf(stderr,"ERROR: there should be %d bytes of data in header->user_data_in_header\n", header->user_data_in_header_size);
      return FALSE;
    }
  }

  // write variable length records variable after variable (to avoid alignment issues)

  for (i = 0; i < header->number_of_variable_length_records; i++)
  {
    // check variable length records contents

    if (header->vlrs[i].reserved != 0xAABB)
    {
//      fprintf(stderr,"WARNING: wrong header->vlrs[%d].reserved: %d != 0xAABB\n", i, header->vlrs[i].reserved);
    }

    // write variable length records variable after variable (to avoid alignment issues)

    if (!stream->put16bitsLE((U8*)&(header->vlrs[i].reserved)))
    {
      fprintf(stderr,"ERROR: writing header->vlrs[%d].reserved\n", i);
      return FALSE;
    }
    if (!stream->putBytes((U8*)header->vlrs[i].user_id, 16))
    {
      fprintf(stderr,"ERROR: writing header->vlrs[%d].user_id\n", i);
      return FALSE;
    }
    if (!stream->put16bitsLE((U8*)&(header->vlrs[i].record_id)))
    {
      fprintf(stderr,"ERROR: writing header->vlrs[%d].record_id\n", i);
      return FALSE;
    }
    if (!stream->put16bitsLE((U8*)&(header->vlrs[i].record_length_after_header)))
    {
      fprintf(stderr,"ERROR: writing header->vlrs[%d].record_length_after_header\n", i);
      return FALSE;
    }
    if (!stream->putBytes((U8*)header->vlrs[i].description, 32))
    {
      fprintf(stderr,"ERROR: writing header->vlrs[%d].description\n", i);
      return FALSE;
    }

    // write the data following the header of the variable length record

    if (header->vlrs[i].record_length_after_header)
    {
      if (header->vlrs[i].data)
      {
        if (!stream->putBytes((U8*)header->vlrs[i].data, header->vlrs[i].record_length_after_header))
        {
          fprintf(stderr,"ERROR: writing %d bytes of data from header->vlrs[%d].data\n", header->vlrs[i].record_length_after_header, i);
          return FALSE;
        }
      }
      else
      {
        fprintf(stderr,"ERROR: there should be %d bytes of data in header->vlrs[%d].data\n", header->vlrs[i].record_length_after_header, i);
        return FALSE;
      }
    }
  }

  // write laszip VLR with compression parameters

  if (laszip)
  {
    // write variable length records variable after variable (to avoid alignment issues)

    U16 reserved = 0xAABB;
    if (!stream->put16bitsLE((U8*)&(reserved)))
    {
      fprintf(stderr,"ERROR: writing reserved %d\n", (I32)reserved);
      return FALSE;
    }
    U8 user_id[16] = "laszip encoded\0";
    if (!stream->putBytes((U8*)user_id, 16))
    {
      fprintf(stderr,"ERROR: writing user_id %s\n", user_id);
      return FALSE;
    }
    U16 record_id = 22204;
    if (!stream->put16bitsLE((U8*)&(record_id)))
    {
      fprintf(stderr,"ERROR: writing record_id %d\n", (I32)record_id);
      return FALSE;
    }
    U16 record_length_after_header = laszip_vlr_data_size;
    if (!stream->put16bitsLE((U8*)&(record_length_after_header)))
    {
      fprintf(stderr,"ERROR: writing record_length_after_header %d\n", (I32)record_length_after_header);
      return FALSE;
    }
    char description[32];
    memset(description, 0, 32);
    sprintf(description, "by laszip of LAStools (%d)", LAS_TOOLS_VERSION);  
    if (!stream->putBytes((U8*)description, 32))
    {
      fprintf(stderr,"ERROR: writing description %s\n", description);
      return FALSE;
    }
    // write the data following the header of the variable length record
    //     U16  compressor                2 bytes 
    //     U32  coder                     2 bytes 
    //     U8   version_major             1 byte 
    //     U8   version_minor             1 byte
    //     U16  version_revision          2 bytes
    //     U32  options                   4 bytes 
    //     I32  chunk_size                4 bytes
    //     I64  number_of_special_evlrs   8 bytes
    //     I64  offset_to_special_evlrs   8 bytes
    //     U16  num_items                 2 bytes
    //        U16 type                2 bytes * num_items
    //        U16 size                2 bytes * num_items
    //        U16 version             2 bytes * num_items
    // which totals 34+6*num_items

    if (!stream->put16bitsLE((U8*)&(laszip->compressor)))
    {
      fprintf(stderr,"ERROR: writing compressor %d\n", (I32)compressor);
      return FALSE;
    }
    if (!stream->put16bitsLE((U8*)&(laszip->coder)))
    {
      fprintf(stderr,"ERROR: writing coder %d\n", (I32)laszip->coder);
      return FALSE;
    }
    if (!stream->putByte(laszip->version_major))
    {
      fprintf(stderr,"ERROR: writing version_major %d\n", laszip->version_major);
      return FALSE;
    }
    if (!stream->putByte(laszip->version_minor))
    {
      fprintf(stderr,"ERROR: writing version_minor %d\n", laszip->version_minor);
      return FALSE;
    }
    if (!stream->put16bitsLE((U8*)&(laszip->version_revision)))
    {
      fprintf(stderr,"ERROR: writing version_revision %d\n", laszip->version_revision);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(laszip->options)))
    {
      fprintf(stderr,"ERROR: writing options %d\n", (I32)laszip->options);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(laszip->chunk_size)))
    {
      fprintf(stderr,"ERROR: writing chunk_size %d\n", laszip->chunk_size);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(laszip->number_of_special_evlrs)))
    {
      fprintf(stderr,"ERROR: writing number_of_special_evlrs %d\n", (I32)laszip->number_of_special_evlrs);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(laszip->offset_to_special_evlrs)))
    {
      fprintf(stderr,"ERROR: writing offset_to_special_evlrs %d\n", (I32)laszip->offset_to_special_evlrs);
      return FALSE;
    }
    if (!stream->put16bitsLE((U8*)&(laszip->num_items)))
    {
      fprintf(stderr,"ERROR: writing num_items %d\n", laszip->num_items);
      return FALSE;
    }
    for (i = 0; i < laszip->num_items; i++)
    {
      if (!stream->put16bitsLE((U8*)&(laszip->items[i].type)))
      {
        fprintf(stderr,"ERROR: writing type %d of item %d\n", laszip->items[i].type, i);
        return FALSE;
      }
      if (!stream->put16bitsLE((U8*)&(laszip->items[i].size)))
      {
        fprintf(stderr,"ERROR: writing size %d of item %d\n", laszip->items[i].size, i);
        return FALSE;
      }
      if (!stream->put16bitsLE((U8*)&(laszip->items[i].version)))
      {
        fprintf(stderr,"ERROR: writing version %d of item %d\n", laszip->items[i].version, i);
        return FALSE;
      }
    }

    delete laszip;
    laszip = 0;
  }

  // write lastiling VLR with the tile parameters

  if (header->vlr_lastiling)
  {
    // write variable length records variable after variable (to avoid alignment issues)

    U16 reserved = 0xAABB;
    if (!stream->put16bitsLE((U8*)&(reserved)))
    {
      fprintf(stderr,"ERROR: writing reserved %d\n", (I32)reserved);
      return FALSE;
    }
    U8 user_id[16] = "LAStools\0\0\0\0\0\0\0";
    if (!stream->putBytes((U8*)user_id, 16))
    {
      fprintf(stderr,"ERROR: writing user_id %s\n", user_id);
      return FALSE;
    }
    U16 record_id = 10;
    if (!stream->put16bitsLE((U8*)&(record_id)))
    {
      fprintf(stderr,"ERROR: writing record_id %d\n", (I32)record_id);
      return FALSE;
    }
    U16 record_length_after_header = 28;
    if (!stream->put16bitsLE((U8*)&(record_length_after_header)))
    {
      fprintf(stderr,"ERROR: writing record_length_after_header %d\n", (I32)record_length_after_header);
      return FALSE;
    }
    CHAR description[32] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    sprintf(description, "tile %s buffer %s", (header->vlr_lastiling->buffer ? "with" : "without"), (header->vlr_lastiling->reversible ? ", reversible" : ""));
    if (!stream->putBytes((U8*)description, 32))
    {
      fprintf(stderr,"ERROR: writing description %s\n", description);
      return FALSE;
    }

    // write the payload of this VLR which contains 28 bytes
    //   U32  level                                          4 bytes 
    //   U32  level_index                                    4 bytes 
    //   U32  implicit_levels + buffer bit + reversible bit  4 bytes 
    //   F32  min_x                                          4 bytes 
    //   F32  max_x                                          4 bytes 
    //   F32  min_y                                          4 bytes 
    //   F32  max_y                                          4 bytes 

    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->level)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->level %u\n", header->vlr_lastiling->level);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->level_index)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->level_index %u\n", header->vlr_lastiling->level_index);
      return FALSE;
    }
    if (!stream->put32bitsLE(((U8*)header->vlr_lastiling)+8))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->implicit_levels %u\n", header->vlr_lastiling->implicit_levels);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->min_x)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->min_x %g\n", header->vlr_lastiling->min_x);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->max_x)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->max_x %g\n", header->vlr_lastiling->max_x);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->min_y)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->min_y %g\n", header->vlr_lastiling->min_y);
      return FALSE;
    }
    if (!stream->put32bitsLE((U8*)&(header->vlr_lastiling->max_y)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lastiling->max_y %g\n", header->vlr_lastiling->max_y);
      return FALSE;
    }
  }

  // write lasoriginal VLR with the original (unbuffered) counts and bounding box extent

  if (header->vlr_lasoriginal)
  {
    // write variable length records variable after variable (to avoid alignment issues)

    U16 reserved = 0xAABB;
    if (!stream->put16bitsLE((U8*)&(reserved)))
    {
      fprintf(stderr,"ERROR: writing reserved %d\n", (I32)reserved);
      return FALSE;
    }
    U8 user_id[16] = "LAStools\0\0\0\0\0\0\0";
    if (!stream->putBytes((U8*)user_id, 16))
    {
      fprintf(stderr,"ERROR: writing user_id %s\n", user_id);
      return FALSE;
    }
    U16 record_id = 20;
    if (!stream->put16bitsLE((U8*)&(record_id)))
    {
      fprintf(stderr,"ERROR: writing record_id %d\n", (I32)record_id);
      return FALSE;
    }
    U16 record_length_after_header = 176;
    if (!stream->put16bitsLE((U8*)&(record_length_after_header)))
    {
      fprintf(stderr,"ERROR: writing record_length_after_header %d\n", (I32)record_length_after_header);
      return FALSE;
    }
    U8 description[32] = "counters and bbox of original\0\0";
    if (!stream->putBytes((U8*)description, 32))
    {
      fprintf(stderr,"ERROR: writing description %s\n", description);
      return FALSE;
    }

    // write the payload of this VLR which contains 176 bytes

    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->number_of_point_records)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->number_of_point_records %u\n", (U32)header->vlr_lasoriginal->number_of_point_records);
      return FALSE;
    }
    for (j = 0; j < 15; j++)
    {
      if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->number_of_points_by_return[j])))
      {
        fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->number_of_points_by_return[%u] %u\n", j, (U32)header->vlr_lasoriginal->number_of_points_by_return[j]);
        return FALSE;
      }
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->min_x)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->min_x %g\n", header->vlr_lasoriginal->min_x);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->max_x)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->max_x %g\n", header->vlr_lasoriginal->max_x);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->min_y)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->min_y %g\n", header->vlr_lasoriginal->min_y);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->max_y)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->max_y %g\n", header->vlr_lasoriginal->max_y);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->min_z)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->min_z %g\n", header->vlr_lasoriginal->min_z);
      return FALSE;
    }
    if (!stream->put64bitsLE((U8*)&(header->vlr_lasoriginal->max_z)))
    {
      fprintf(stderr,"ERROR: writing header->vlr_lasoriginal->max_z %g\n", header->vlr_lasoriginal->max_z);
      return FALSE;
    }
  }

  // write any number of user-defined bytes that might have been added after the header

  if (header->user_data_after_header_size)
  {
    if (header->user_data_after_header)
    {
      if (!stream->putBytes((U8*)header->user_data_after_header, header->user_data_after_header_size))
      {
        fprintf(stderr,"ERROR: writing %d bytes of data from header->user_data_after_header\n", header->user_data_after_header_size);
        return FALSE;
      }
    }
    else
    {
      fprintf(stderr,"ERROR: there should be %d bytes of data in header->user_data_after_header\n", header->user_data_after_header_size);
      return FALSE;
    }
  }

  // initialize the point writer

  if (!writer->init(stream)) return FALSE;

  npoints = (header->number_of_point_records ? header->number_of_point_records : header->extended_number_of_point_records);
  p_count = 0;

  return TRUE;
}
示例#2
0
int32_t
laszip_open_reader(laszip_dll_struct * laszip_dll, const char* file_name, laszip_BOOL* is_compressed)
{
  if (laszip_dll == 0) return 1;

  try
  {
    if (file_name == 0)
    {
      sprintf(laszip_dll->error, "char pointer 'file_name' is zero");
      return 1;
    }

    if (is_compressed == 0)
    {
      sprintf(laszip_dll->error, "laszip_BOOL pointer 'is_compressed' is zero");
      return 1;
    }

    if (laszip_dll->reader)
    {
      sprintf(laszip_dll->error, "reader is already open");
      return 1;
    }

    // open the file

    laszip_dll->file = fopen(file_name, "rb");

    if (laszip_dll->file == 0)
    {
      sprintf(laszip_dll->error, "cannot open file '%s'", file_name);
      return 1;
    }

    if (setvbuf(laszip_dll->file, NULL, _IOFBF, 262144) != 0)
    {
      sprintf(laszip_dll->warning, "setvbuf() failed with buffer size 262144\n");
    }

    laszip_dll->streamin = new ByteStreamIn(laszip_dll->file);

    if (laszip_dll->streamin == 0)
    {
      sprintf(laszip_dll->error, "could not alloc ByteStreamInFile");
      return 1;
    }

    // read the header variable after variable

    U32 i;

    CHAR file_signature[5];
    try { laszip_dll->streamin->getBytes((U8*)file_signature, 4); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.file_signature");
      return 1;
    }
    if (strncmp(file_signature, "LASF", 4) != 0)
    {
      sprintf(laszip_dll->error, "wrong file_signature. not a LAS/LAZ file.");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.file_source_ID)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.file_source_ID");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.global_encoding)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.global_encoding");
      return 1;
    }
    try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.project_ID_GUID_data_1)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.project_ID_GUID_data_1");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.project_ID_GUID_data_2)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.project_ID_GUID_data_2");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.project_ID_GUID_data_3)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.project_ID_GUID_data_3");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.project_ID_GUID_data_4, 8); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.project_ID_GUID_data_4");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)&(laszip_dll->header.version_major), 1); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.version_major");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)&(laszip_dll->header.version_minor), 1); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.version_minor");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.system_identifier, 32); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.system_identifier");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.generating_software, 32); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.generating_software");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.file_creation_day)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.file_creation_day");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.file_creation_year)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.file_creation_year");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.header_size)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.header_size");
      return 1;
    }
    try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.offset_to_point_data)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.offset_to_point_data");
      return 1;
    }
    try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.number_of_variable_length_records)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.number_of_variable_length_records");
      return 1;
    }
    try { laszip_dll->streamin->getBytes((U8*)&(laszip_dll->header.point_data_format), 1); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.point_data_format");
      return 1;
    }
    try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.point_data_record_length)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.point_data_record_length");
      return 1;
    }
    try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.number_of_point_records)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.number_of_point_records");
      return 1;
    }
    for (i = 0; i < 5; i++)
    {
      try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.number_of_points_by_return[i])); } catch(...)
      {
        sprintf(laszip_dll->error, "reading header.number_of_points_by_return %d", i);
        return 1;
      }
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.x_scale_factor)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.x_scale_factor");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.y_scale_factor)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.y_scale_factor");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.z_scale_factor)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.z_scale_factor");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.x_offset)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.x_offset");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.y_offset)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.y_offset");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.z_offset)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.z_offset");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.max_x)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.max_x");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.min_x)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.min_x");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.max_y)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.max_y");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.min_y)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.min_y");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.max_z)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.max_z");
      return 1;
    }
    try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.min_z)); } catch(...)
    {
      sprintf(laszip_dll->error, "reading header.min_z");
      return 1;
    }

    // special handling for LAS 1.3
    if ((laszip_dll->header.version_major == 1) && (laszip_dll->header.version_minor >= 3))
    {
      if (laszip_dll->header.header_size < 235)
      {
        sprintf(laszip_dll->error, "for LAS 1.%d header_size should at least be 235 but it is only %d", laszip_dll->header.version_minor, laszip_dll->header.header_size);
        return 1;
      }
      else
      {
        try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.start_of_waveform_data_packet_record)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.start_of_waveform_data_packet_record");
          return 1;
        }
        laszip_dll->header.user_data_in_header_size = laszip_dll->header.header_size - 235;
      }
    }
    else
    {
      laszip_dll->header.user_data_in_header_size = laszip_dll->header.header_size - 227;
    }

    // special handling for LAS 1.4
    if ((laszip_dll->header.version_major == 1) && (laszip_dll->header.version_minor >= 4))
    {
      if (laszip_dll->header.header_size < 375)
      {
        sprintf(laszip_dll->error, "for LAS 1.%d header_size should at least be 375 but it is only %d", laszip_dll->header.version_minor, laszip_dll->header.header_size);
        return 1;
      }
      else
      {
        try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.start_of_first_extended_variable_length_record)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.start_of_first_extended_variable_length_record");
          return 1;
        }
        try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip_dll->header.number_of_extended_variable_length_records)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.number_of_extended_variable_length_records");
          return 1;
        }
        try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.extended_number_of_point_records)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.extended_number_of_point_records");
          return 1;
        }
        for (i = 0; i < 15; i++)
        {
          try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip_dll->header.extended_number_of_points_by_return[i])); } catch(...)
          {
            sprintf(laszip_dll->error, "reading header.extended_number_of_points_by_return[%d]", i);
            return 1;
          }
        }
        laszip_dll->header.user_data_in_header_size = laszip_dll->header.header_size - 375;
      }
    }

    // load any number of user-defined bytes that might have been added to the header
    if (laszip_dll->header.user_data_in_header_size)
    {
      if (laszip_dll->header.user_data_in_header)
      {
        delete [] laszip_dll->header.user_data_in_header;
      }
      laszip_dll->header.user_data_in_header = new U8[laszip_dll->header.user_data_in_header_size];

      try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.user_data_in_header, laszip_dll->header.user_data_in_header_size); } catch(...)
      {
        sprintf(laszip_dll->error, "reading %u bytes of data into header.user_data_in_header", laszip_dll->header.user_data_in_header_size);
        return 1;
      }
    }

    // read variable length records into the header

    U32 vlrs_size = 0;
    LASzip* laszip = 0;

    if (laszip_dll->header.number_of_variable_length_records)
    {
      U32 i;

      laszip_dll->header.vlrs = (laszip_vlr*)malloc(sizeof(laszip_vlr)*laszip_dll->header.number_of_variable_length_records);

      if (laszip_dll->header.vlrs == 0)
      {
        sprintf(laszip_dll->error, "allocating %u VLRs", laszip_dll->header.number_of_variable_length_records);
        return 1;
      }

      for (i = 0; i < laszip_dll->header.number_of_variable_length_records; i++)
      {
        // make sure there are enough bytes left to read a variable length record before the point block starts

        if (((int)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size) < 54)
        {
          sprintf(laszip_dll->warning, "only %d bytes until point block after reading %d of %d vlrs. skipping remaining vlrs ...", (int)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size, i, laszip_dll->header.number_of_variable_length_records);
          laszip_dll->header.number_of_variable_length_records = i;
          break;
        }

        // read variable length records variable after variable (to avoid alignment issues)

        try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.vlrs[i].reserved)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.vlrs[%u].reserved", i);
          return 1;
        }

        try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.vlrs[i].user_id, 16); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.vlrs[%u].user_id", i);
          return 1;
        }
        try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.vlrs[i].record_id)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.vlrs[%u].record_id", i);
          return 1;
        }
        try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip_dll->header.vlrs[i].record_length_after_header)); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.vlrs[%u].record_length_after_header", i);
          return 1;
        }
        try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.vlrs[i].description, 32); } catch(...)
        {
          sprintf(laszip_dll->error, "reading header.vlrs[%u].description", i);
          return 1;
        }

        // keep track on the number of bytes we have read so far

        vlrs_size += 54;

        // check variable length record contents

        if (laszip_dll->header.vlrs[i].reserved != 0xAABB)
        {
          sprintf(laszip_dll->warning,"wrong header.vlrs[%d].reserved: %d != 0xAABB", i, laszip_dll->header.vlrs[i].reserved);
        }

        // make sure there are enough bytes left to read the data of the variable length record before the point block starts

        if (((int)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size) < laszip_dll->header.vlrs[i].record_length_after_header)
        {
          sprintf(laszip_dll->warning, "only %d bytes until point block when trying to read %d bytes into header.vlrs[%d].data", (int)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size, laszip_dll->header.vlrs[i].record_length_after_header, i);
          laszip_dll->header.vlrs[i].record_length_after_header = (int)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size;
        }

        // load data following the header of the variable length record

        if (laszip_dll->header.vlrs[i].record_length_after_header)
        {
          if ((strcmp(laszip_dll->header.vlrs[i].user_id, "laszip encoded") == 0) && (laszip_dll->header.vlrs[i].record_id == 22204))
          {
            if (laszip)
            {
              delete laszip;
            }

            laszip = new LASzip();

            if (laszip == 0)
            {
              sprintf(laszip_dll->error, "could not alloc LASzip");
              return 1;
            }

            // read the LASzip VLR payload

            //     U16  compressor                2 bytes
            //     U32  coder                     2 bytes
            //     U8   version_major             1 byte
            //     U8   version_minor             1 byte
            //     U16  version_revision          2 bytes
            //     U32  options                   4 bytes
            //     I32  chunk_size                4 bytes
            //     I64  number_of_special_evlrs   8 bytes
            //     I64  offset_to_special_evlrs   8 bytes
            //     U16  num_items                 2 bytes
            //        U16 type                2 bytes * num_items
            //        U16 size                2 bytes * num_items
            //        U16 version             2 bytes * num_items
            // which totals 34+6*num_items

            try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->compressor)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading compressor %d", (I32)laszip->compressor);
              return 1;
            }
            try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->coder)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading coder %d", (I32)laszip->coder);
              return 1;
            }
            try { laszip_dll->streamin->getBytes((U8*)&(laszip->version_major), 1); } catch(...)
            {
              sprintf(laszip_dll->error, "reading version_major %d", (I32)laszip->version_major);
              return 1;
            }
            try { laszip_dll->streamin->getBytes((U8*)&(laszip->version_minor), 1); } catch(...)
            {
              sprintf(laszip_dll->error, "reading version_minor %d", (I32)laszip->version_minor);
              return 1;
            }
            try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->version_revision)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading version_revision %d", (I32)laszip->version_revision);
              return 1;
            }
            try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip->options)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading options %u", laszip->options);
              return 1;
            }
            try { laszip_dll->streamin->get32bitsLE((U8*)&(laszip->chunk_size)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading chunk_size %u", laszip->chunk_size);
              return 1;
            }
            try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip->number_of_special_evlrs)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading number_of_special_evlrs %d", (I32)laszip->number_of_special_evlrs);
              return 1;
            }
            try { laszip_dll->streamin->get64bitsLE((U8*)&(laszip->offset_to_special_evlrs)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading offset_to_special_evlrs %d", (I32)laszip->offset_to_special_evlrs);
              return 1;
            }
            try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->num_items)); } catch(...)
            {
              sprintf(laszip_dll->error, "reading num_items %d", (I32)laszip->num_items);
              return 1;
            }
            laszip->items = new LASitem[laszip->num_items];
            U32 j;
            for (j = 0; j < laszip->num_items; j++)
            {
              U16 type;
              try { laszip_dll->streamin->get16bitsLE((U8*)&type); } catch(...)
              {
                sprintf(laszip_dll->error, "reading type of item %u", j);
                return 1;
              }
              laszip->items[j].type = (LASitem::Type)type;
              try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->items[j].size)); } catch(...)
              {
                sprintf(laszip_dll->error, "reading size of item %u", j);
                return 1;
              }
              try { laszip_dll->streamin->get16bitsLE((U8*)&(laszip->items[j].version)); } catch(...)
              {
                sprintf(laszip_dll->error, "reading version of item %u", j);
                return 1;
              }
            }
          }
          else
          {
            laszip_dll->header.vlrs[i].data = new U8[laszip_dll->header.vlrs[i].record_length_after_header];

            try { laszip_dll->streamin->getBytes(laszip_dll->header.vlrs[i].data, laszip_dll->header.vlrs[i].record_length_after_header); } catch(...)
            {
              sprintf(laszip_dll->error, "reading %d bytes of data into header.vlrs[%u].data", (I32)laszip_dll->header.vlrs[i].record_length_after_header, i);
              return 1;
            }
          }
        }
        else
        {
          laszip_dll->header.vlrs[i].data = 0;
        }

        // keep track on the number of bytes we have read so far

        vlrs_size += laszip_dll->header.vlrs[i].record_length_after_header;

        // special handling for LASzip VLR

        if ((strcmp(laszip_dll->header.vlrs[i].user_id, "laszip encoded") == 0) && (laszip_dll->header.vlrs[i].record_id == 22204))
        {
          // we take our the VLR for LASzip away
          laszip_dll->header.offset_to_point_data -= (54+laszip_dll->header.vlrs[i].record_length_after_header);
          vlrs_size -= (54+laszip_dll->header.vlrs[i].record_length_after_header);
          i--;
          laszip_dll->header.number_of_variable_length_records--;
          // free or resize the VLR array
          if (laszip_dll->header.number_of_variable_length_records == 0)
          {
            free(laszip_dll->header.vlrs);
            laszip_dll->header.vlrs = 0;
          }
          else
          {
            laszip_dll->header.vlrs = (laszip_vlr*)realloc(laszip_dll->header.vlrs, sizeof(laszip_vlr)*laszip_dll->header.number_of_variable_length_records);
          }
        }
      }
    }

    // load any number of user-defined bytes that might have been added after the header

    laszip_dll->header.user_data_after_header_size = (I32)laszip_dll->header.offset_to_point_data - vlrs_size - laszip_dll->header.header_size;
    if (laszip_dll->header.user_data_after_header_size)
    {
      if (laszip_dll->header.user_data_after_header)
      {
        delete [] laszip_dll->header.user_data_after_header;
      }
      laszip_dll->header.user_data_after_header = new U8[laszip_dll->header.user_data_after_header_size];

      try { laszip_dll->streamin->getBytes((U8*)laszip_dll->header.user_data_after_header, laszip_dll->header.user_data_after_header_size); } catch(...)
      {
        sprintf(laszip_dll->error, "reading %u bytes of data into header.user_data_after_header", laszip_dll->header.user_data_after_header_size);
        return 1;
      }
    }

    // remove extra bits in point data type

    if ((laszip_dll->header.point_data_format & 128) || (laszip_dll->header.point_data_format & 64))
    {
      if (!laszip)
      {
        sprintf(laszip_dll->error, "this file was compressed with an experimental version of LASzip. contact '*****@*****.**' for assistance");
        return 1;
      }
      laszip_dll->header.point_data_format &= 127;
    }

    // check if file is compressed

    if (laszip)
    {
      // yes. check the compressor state
      *is_compressed = 1;
      if (!laszip->check())
      {
        sprintf(laszip_dll->error, "%s upgrade to the latest release of LASzip or contact '*****@*****.**' for assistance", laszip->get_error());
        return 1;
      }
    }
    else
    {
      // no. setup an un-compressed read
      *is_compressed = 0;
      laszip = new LASzip;
      if (laszip == 0)
      {
        sprintf(laszip_dll->error, "could not alloc LASzip");
        return 1;
      }
      if (!laszip->setup(laszip_dll->header.point_data_format, laszip_dll->header.point_data_record_length, LASZIP_COMPRESSOR_NONE))
      {
        sprintf(laszip_dll->error, "invalid combination of point_data_format %d and point_data_record_length %d", (I32)laszip_dll->header.point_data_format, (I32)laszip_dll->header.point_data_record_length);
        return 1;
      }
    }

    // create point's item pointers

    laszip_dll->point_items = new U8*[laszip->num_items];

    if (laszip_dll->point_items == 0)
    {
      sprintf(laszip_dll->error, "could not alloc point_items");
      return 1;
    }

    for (i = 0; i < laszip->num_items; i++)
    {
      switch (laszip->items[i].type)
      {
      case LASitem::POINT14:
      case LASitem::POINT10:
        laszip_dll->point_items[i] = (U8*)&(laszip_dll->point.X);
        break;
      case LASitem::GPSTIME11:
        laszip_dll->point_items[i] = (U8*)&(laszip_dll->point.gps_time);
        break;
      case LASitem::RGBNIR14:
      case LASitem::RGB12:
        laszip_dll->point_items[i] = (U8*)laszip_dll->point.rgb;
        break;
      case LASitem::WAVEPACKET13:
        laszip_dll->point_items[i] = (U8*)&(laszip_dll->point.wave_packet);
        break;
      case LASitem::BYTE:
        laszip_dll->point.num_extra_bytes = laszip->items[i].size;
        if (laszip_dll->point.extra_bytes) delete [] laszip_dll->point.extra_bytes;
        laszip_dll->point.extra_bytes = new U8[laszip_dll->point.num_extra_bytes];
        laszip_dll->point_items[i] = laszip_dll->point.extra_bytes;
        break;
      default:
        sprintf(laszip_dll->error, "unknown LASitem type %d", (I32)laszip->items[i].type);
        return 1;
      }
    }

    // create the point reader

    laszip_dll->reader = new LASreadPoint();
    if (laszip_dll->reader == 0)
    {
      sprintf(laszip_dll->error, "could not alloc LASreadPoint");
      return 1;
    }

    if (!laszip_dll->reader->setup(laszip->num_items, laszip->items, laszip))
    {
      sprintf(laszip_dll->error, "setup of LASreadPoint failed");
      return 1;
    }

    if (!laszip_dll->reader->init(laszip_dll->streamin))
    {
      sprintf(laszip_dll->error, "init of LASreadPoint failed");
      return 1;
    }

    delete laszip;

    // set the point number and point count

    laszip_dll->npoints = (laszip_dll->header.number_of_point_records ? laszip_dll->header.number_of_point_records : laszip_dll->header.extended_number_of_point_records);
    laszip_dll->p_count = 0;
  }
  catch (...)
  {
    sprintf(laszip_dll->error, "internal error in laszip_open_reader");
    return 1;
  }

  laszip_dll->error[0] = '\0';
  return 0;
}
示例#3
0
static void run_test(const char* filename, PointData& data, unsigned short compressor, int requested_version=-1, int chunk_size=-1, bool random_seeks=false)
{
  //
  // COMPRESSION
  //

  // setting up LASzip parameters
  LASzip laszip;
  if (!laszip.setup(data.point_type, data.point_size, compressor))
  {
    log("ERROR on laszip.setup(): %s\n", laszip.get_error());
  }
  if (requested_version > -1) laszip.request_version((unsigned short)requested_version);
  if (chunk_size > -1) laszip.set_chunk_size((unsigned int)chunk_size);

  // packing up LASzip
  unsigned char* bytes;
  int num;
  if (!laszip.pack(bytes, num))
  {
    log("ERROR on laszip.pack(): %s\n", laszip.get_error());
  }

  // creating the output stream
  OStream* ost = new OStream(settings->use_iostream, filename);

  // creating the zipper
  LASzipper* laszipper = make_zipper(ost, &laszip);

  // allocating the data to read from
  data.setup(laszip.num_items, laszip.items);

  // writing the points
  if (chunk_size == 0)
  {
    if (random_seeks)
      write_points_explicit_chunk_seek(laszipper, data);
    else
      write_points_explicit_chunk(laszipper, data);
  }
  else
  {
    if (random_seeks)
      write_points_seek(laszipper, data);
    else
      write_points(laszipper, data);
  }

  // cleaning up
  delete laszipper;
  delete ost;

  //
  // DECOMPRESSION
  //

  // setting up LASzip parameters
  LASzip laszip_dec;
  if (!laszip_dec.unpack(bytes, num))
  {
    log("ERROR on laszip_dec.unpack(): %s\n", laszip_dec.get_error());
  }

  // creating the input stream
  IStream* ist = new IStream(settings->use_iostream, filename);

  // creating the unzipper
  LASunzipper* lasunzipper = make_unzipper(ist, &laszip_dec);

  // allocating the data to write into
  data.setup(laszip_dec.num_items, laszip_dec.items);
  
  // reading the points
  if (random_seeks)
    read_points_seek(lasunzipper, data);
  else
    read_points(lasunzipper, data);

  // cleaning up
  delete lasunzipper;
  delete ist;

  return;
}