public int laszip_close_reader() { if(reader==null) { error="closing reader before it was opened"; return 1; } try { if(!reader.done()) { error="done of LASreadPoint failed"; return 1; } reader=null; streamin.Close(); streamin=null; } catch { error="internal error in laszip_close_reader"; return 1; } error=null; return 0; }
public int laszip_clean() { try { if(reader!=null) { error="cannot clean while reader is open."; return 1; } if(writer!=null) { error="cannot clean while writer is open."; return 1; } // zero everything header.file_source_ID=0; header.global_encoding=0; header.project_ID_GUID_data_1=0; header.project_ID_GUID_data_2=0; header.project_ID_GUID_data_3=0; header.project_ID_GUID_data_4=new byte[8]; header.version_major=0; header.version_minor=0; header.system_identifier=new byte[32]; header.generating_software=new byte[32]; header.file_creation_day=0; header.file_creation_year=0; header.header_size=0; header.offset_to_point_data=0; header.number_of_variable_length_records=0; header.point_data_format=0; header.point_data_record_length=0; header.number_of_point_records=0; header.number_of_points_by_return=new uint[5]; header.x_scale_factor=0; header.y_scale_factor=0; header.z_scale_factor=0; header.x_offset=0; header.y_offset=0; header.z_offset=0; header.max_x=0; header.min_x=0; header.max_y=0; header.min_y=0; header.max_z=0; header.min_z=0; header.start_of_waveform_data_packet_record=0; header.start_of_first_extended_variable_length_record=0; header.number_of_extended_variable_length_records=0; header.extended_number_of_point_records=0; header.extended_number_of_points_by_return=new ulong[15]; header.user_data_in_header_size=0; header.user_data_in_header=null; header.vlrs=null; header.user_data_after_header_size=0; header.user_data_after_header=null; p_count=0; npoints=0; point.X=0; point.Y=0; point.Z=0; point.intensity=0; point.return_number=0;// : 3; point.number_of_returns_of_given_pulse=0;// : 3; point.scan_direction_flag=0;// : 1; point.edge_of_flight_line=0;// : 1; point.classification=0; point.scan_angle_rank=0; point.user_data=0; point.point_source_ID=0; point.gps_time=0; point.rgb=new ushort[4]; point.wave_packet=new byte[29]; point.extended_point_type=0;// : 2; point.extended_scanner_channel=0;// : 2; point.extended_classification_flags=0;// : 4; point.extended_classification=0; point.extended_return_number=0;// : 4; point.extended_number_of_returns_of_given_pulse=0;// : 4; point.extended_scan_angle=0; point.num_extra_bytes=0; point.extra_bytes=null; streamin=null; reader=null; streamout=null; writer=null; error=null; warning=null; // create default header Array.Copy(Encoding.ASCII.GetBytes(string.Format("LASzip DLL {0}.{1} r{2} ({3})", LASzip.VERSION_MAJOR, LASzip.VERSION_MINOR, LASzip.VERSION_REVISION, LASzip.VERSION_BUILD_DATE)), header.generating_software, 32); header.version_major=1; header.version_minor=2; header.header_size=227; header.offset_to_point_data=227; header.point_data_format=1; header.point_data_record_length=28; header.x_scale_factor=0.01; header.y_scale_factor=0.01; header.z_scale_factor=0.01; } catch { error="internal error in laszip_clean"; return 1; } return 0; }
public int laszip_open_reader(Stream stream, ref bool is_compressed) { if (stream == null) { error = "file stream is empty"; return 1; } streamin = stream; try { byte[] buffer=new byte[32]; #region read the header variable after variable if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.file_signature"; return 1; } if(buffer[0]!='L'&&buffer[1]!='A'&&buffer[2]!='S'&&buffer[3]!='F') { error="wrong file_signature. not a LAS/LAZ file."; return 1; } if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.file_source_ID"; return 1; } header.file_source_ID=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.global_encoding"; return 1; } header.global_encoding=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.project_ID_GUID_data_1"; return 1; } header.project_ID_GUID_data_1=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.project_ID_GUID_data_2"; return 1; } header.project_ID_GUID_data_2=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.project_ID_GUID_data_3"; return 1; } header.project_ID_GUID_data_3=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(header.project_ID_GUID_data_4, 0, 8)!=8) { error="reading header.project_ID_GUID_data_4"; return 1; } if(streamin.Read(buffer, 0, 1)!=1) { error="reading header.version_major"; return 1; } header.version_major=buffer[0]; if(streamin.Read(buffer, 0, 1)!=1) { error="reading header.version_minor"; return 1; } header.version_minor=buffer[0]; if(streamin.Read(header.system_identifier, 0, 32)!=32) { error="reading header.system_identifier"; return 1; } if(streamin.Read(header.generating_software, 0, 32)!=32) { error="reading header.generating_software"; return 1; } if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.file_creation_day"; return 1; } header.file_creation_day=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.file_creation_year"; return 1; } header.file_creation_year=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.header_size"; return 1; } header.header_size=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.offset_to_point_data"; return 1; } header.offset_to_point_data=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.number_of_variable_length_records"; return 1; } header.number_of_variable_length_records=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 1)!=1) { error="reading header.point_data_format"; return 1; } header.point_data_format=buffer[0]; if(streamin.Read(buffer, 0, 2)!=2) { error="reading header.point_data_record_length"; return 1; } header.point_data_record_length=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.number_of_point_records"; return 1; } header.number_of_point_records=BitConverter.ToUInt32(buffer, 0); for(int i=0; i<5; i++) { if(streamin.Read(buffer, 0, 4)!=4) { error=string.Format("reading header.number_of_points_by_return {0}", i); return 1; } header.number_of_points_by_return[i]=BitConverter.ToUInt32(buffer, 0); } if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.x_scale_factor"; return 1; } header.x_scale_factor=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.y_scale_factor"; return 1; } header.y_scale_factor=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.z_scale_factor"; return 1; } header.z_scale_factor=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.x_offset"; return 1; } header.x_offset=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.y_offset"; return 1; } header.y_offset=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.z_offset"; return 1; } header.z_offset=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.max_x"; return 1; } header.max_x=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.min_x"; return 1; } header.min_x=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.max_y"; return 1; } header.max_y=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.min_y"; return 1; } header.min_y=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.max_z"; return 1; } header.max_z=BitConverter.ToDouble(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.min_z"; return 1; } header.min_z=BitConverter.ToDouble(buffer, 0); // special handling for LAS 1.3 if((header.version_major==1)&&(header.version_minor>=3)) { if(header.header_size<235) { error=string.Format("for LAS 1.{0} header_size should at least be 235 but it is only {1}", header.version_minor, header.header_size); return 1; } else { if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.start_of_waveform_data_packet_record"; return 1; } header.start_of_waveform_data_packet_record=BitConverter.ToUInt64(buffer, 0); header.user_data_in_header_size=(uint)header.header_size-235; } } else { header.user_data_in_header_size=(uint)header.header_size-227; } // special handling for LAS 1.4 if((header.version_major==1)&&(header.version_minor>=4)) { if(header.header_size<375) { error=string.Format("for LAS 1.{0} header_size should at least be 375 but it is only {1}", header.version_minor, header.header_size); return 1; } else { if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.start_of_first_extended_variable_length_record"; return 1; } header.start_of_first_extended_variable_length_record=BitConverter.ToUInt64(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading header.number_of_extended_variable_length_records"; return 1; } header.number_of_extended_variable_length_records=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading header.extended_number_of_point_records"; return 1; } header.extended_number_of_point_records=BitConverter.ToUInt64(buffer, 0); for(int i=0; i<15; i++) { if(streamin.Read(buffer, 0, 8)!=8) { error=string.Format("reading header.extended_number_of_points_by_return[{0}]", i); return 1; } header.extended_number_of_points_by_return[i]=BitConverter.ToUInt64(buffer, 0); } header.user_data_in_header_size=(uint)header.header_size-375; } } // load any number of user-defined bytes that might have been added to the header if(header.user_data_in_header_size!=0) { header.user_data_in_header=new byte[header.user_data_in_header_size]; if(streamin.Read(header.user_data_in_header, 0, (int)header.user_data_in_header_size)!=header.user_data_in_header_size) { error=string.Format("reading {0} bytes of data into header.user_data_in_header", header.user_data_in_header_size); return 1; } } #endregion #region read variable length records into the header uint vlrs_size=0; LASzip laszip=null; if(header.number_of_variable_length_records!=0) { header.vlrs=new List<laszip_vlr>(); for(int i=0; i<header.number_of_variable_length_records; i++) { header.vlrs.Add(new laszip_vlr()); // make sure there are enough bytes left to read a variable length record before the point block starts if(((int)header.offset_to_point_data-vlrs_size-header.header_size)<54) { warning=string.Format("only {0} bytes until point block after reading {1} of {2} vlrs. skipping remaining vlrs ...", (int)header.offset_to_point_data-vlrs_size-header.header_size, i, header.number_of_variable_length_records); header.number_of_variable_length_records=(uint)i; break; } // read variable length records variable after variable (to avoid alignment issues) if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading header.vlrs[{0}].reserved", i); return 1; } header.vlrs[i].reserved=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(header.vlrs[i].user_id, 0, 16)!=16) { error=string.Format("reading header.vlrs[{0}].user_id", i); return 1; } if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading header.vlrs[{0}].record_id", i); return 1; } header.vlrs[i].record_id=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading header.vlrs[{0}].record_length_after_header", i); return 1; } header.vlrs[i].record_length_after_header=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(header.vlrs[i].description, 0, 32)!=32) { error=string.Format("reading header.vlrs[{0}].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(header.vlrs[i].reserved!=0xAABB) { warning=string.Format("wrong header.vlrs[{0}].reserved: {1} != 0xAABB", i, 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)header.offset_to_point_data-vlrs_size-header.header_size)<header.vlrs[i].record_length_after_header) { warning=string.Format("only {0} bytes until point block when trying to read {1} bytes into header.vlrs[{2}].data", (int)header.offset_to_point_data-vlrs_size-header.header_size, header.vlrs[i].record_length_after_header, i); header.vlrs[i].record_length_after_header=(ushort)(header.offset_to_point_data-vlrs_size-header.header_size); } string userid=""; for(int a=0; a<header.vlrs[i].user_id.Length; a++) { if(header.vlrs[i].user_id[a]==0) break; userid+=(char)header.vlrs[i].user_id[a]; } // load data following the header of the variable length record if(header.vlrs[i].record_length_after_header!=0) { if(userid=="laszip encoded") { laszip=new LASzip(); // 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 if(streamin.Read(buffer, 0, 2)!=2) { error="reading compressor"; return 1; } laszip.compressor=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading coder"; return 1; } laszip.coder=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 1)!=1) { error="reading version_major"; return 1; } laszip.version_major=buffer[0]; if(streamin.Read(buffer, 0, 1)!=1) { error="reading version_minor"; return 1; } laszip.version_minor=buffer[0]; if(streamin.Read(buffer, 0, 2)!=2) { error="reading version_revision"; return 1; } laszip.version_revision=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading options"; return 1; } laszip.options=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 4)!=4) { error="reading chunk_size"; return 1; } laszip.chunk_size=BitConverter.ToUInt32(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading number_of_special_evlrs"; return 1; } laszip.number_of_special_evlrs=BitConverter.ToInt64(buffer, 0); if(streamin.Read(buffer, 0, 8)!=8) { error="reading offset_to_special_evlrs"; return 1; } laszip.offset_to_special_evlrs=BitConverter.ToInt64(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error="reading num_items"; return 1; } laszip.num_items=BitConverter.ToUInt16(buffer, 0); laszip.items=new LASitem[laszip.num_items]; for(int j=0; j<laszip.num_items; j++) { laszip.items[j]=new LASitem(); if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading type of item {0}", j); return 1; } laszip.items[j].type=(LASitem.Type)BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading size of item {0}", j); return 1; } laszip.items[j].size=BitConverter.ToUInt16(buffer, 0); if(streamin.Read(buffer, 0, 2)!=2) { error=string.Format("reading version of item {0}", j); return 1; } laszip.items[j].version=BitConverter.ToUInt16(buffer, 0); } } else { header.vlrs[i].data=new byte[header.vlrs[i].record_length_after_header]; if(streamin.Read(header.vlrs[i].data, 0, header.vlrs[i].record_length_after_header)!=header.vlrs[i].record_length_after_header) { error=string.Format("reading {0} bytes of data into header.vlrs[{1}].data", header.vlrs[i].record_length_after_header, i); return 1; } } } else { header.vlrs[i].data=null; } // keep track on the number of bytes we have read so far vlrs_size+=header.vlrs[i].record_length_after_header; // special handling for LASzip VLR if(userid=="laszip encoded") { // we take our the VLR for LASzip away header.offset_to_point_data-=(uint)(54+header.vlrs[i].record_length_after_header); vlrs_size-=(uint)(54+header.vlrs[i].record_length_after_header); header.vlrs.RemoveAt(i); i--; header.number_of_variable_length_records--; } } } #endregion // load any number of user-defined bytes that might have been added after the header header.user_data_after_header_size=header.offset_to_point_data-vlrs_size-header.header_size; if(header.user_data_after_header_size!=0) { header.user_data_after_header=new byte[header.user_data_after_header_size]; if(streamin.Read(header.user_data_after_header, 0, (int)header.user_data_after_header_size)!=header.user_data_after_header_size) { error=string.Format("reading {0} bytes of data into header.user_data_after_header", header.user_data_after_header_size); return 1; } } // remove extra bits in point data type if((header.point_data_format&128)!=0||(header.point_data_format&64)!=0) { if(laszip==null) { error="this file was compressed with an experimental version of LASzip. contact '*****@*****.**' for assistance"; return 1; } header.point_data_format&=127; } // check if file is compressed if(laszip!=null) { // yes. check the compressor state is_compressed=true; if(!laszip.check()) { error=string.Format("{0} upgrade to the latest release of LAStools (with LASzip) or contact '*****@*****.**' for assistance", laszip.get_error()); return 1; } } else { // no. setup an un-compressed read is_compressed=false; laszip=new LASzip(); if(!laszip.setup(header.point_data_format, header.point_data_record_length, LASzip.COMPRESSOR_NONE)) { error=string.Format("invalid combination of point_data_format {0} and point_data_record_length {1}", header.point_data_format, header.point_data_record_length); return 1; } } // create point's item pointers for(int i=0; i<laszip.num_items; i++) { switch(laszip.items[i].type) { case LASitem.Type.POINT14: case LASitem.Type.POINT10: case LASitem.Type.GPSTIME11: case LASitem.Type.RGBNIR14: case LASitem.Type.RGB12: case LASitem.Type.WAVEPACKET13: break; case LASitem.Type.BYTE: point.num_extra_bytes=laszip.items[i].size; point.extra_bytes=new byte[point.num_extra_bytes]; break; default: error=string.Format("unknown LASitem type {0}", laszip.items[i].type); return 1; } } // create the point reader reader=new LASreadPoint(); if(!reader.setup(laszip.num_items, laszip.items, laszip)) { error="setup of LASreadPoint failed"; return 1; } if(!reader.init(streamin)) { error="init of LASreadPoint failed"; return 1; } laszip=null; // set the point number and point count npoints=header.number_of_point_records; p_count=0; } catch { error="internal error in laszip_open_reader"; return 1; } error=null; return 0; }