public int laszip_open_writer(string file_name, bool compress) { if(file_name==null||file_name.Length==0) { error="string file_name pointer is zero"; return 1; } if(reader!=null) { error="reader is already open"; return 1; } if(writer!=null) { error="writer is already open"; return 1; } try { #region check header and prepare point uint vlrs_size=0; if(header.version_major!=1) { error=string.Format("unknown LAS version {0}.{1}", header.version_major, header.version_minor); return 1; } if(compress&&(header.point_data_format>5)) { error=string.Format("compressor does not yet support point data format {1}", header.point_data_format); return 1; } if(header.number_of_variable_length_records!=0) { if(header.vlrs==null) { error=string.Format("number_of_variable_length_records is {0} but vlrs pointer is zero", header.number_of_variable_length_records); return 1; } for(int i=0; i<header.number_of_variable_length_records; i++) { vlrs_size+=54; if(header.vlrs[i].record_length_after_header!=0) { if(header.vlrs==null) { error=string.Format("vlrs[{0}].record_length_after_header is {1} but vlrs[{0}].data pointer is zero", i, header.vlrs[i].record_length_after_header); return 1; } vlrs_size+=header.vlrs[i].record_length_after_header; } } } if((vlrs_size+header.header_size+header.user_data_after_header_size)!=header.offset_to_point_data) { error=string.Format("header_size ({0}) plus vlrs_size ({1}) plus user_data_after_header_size ({2}) does not equal offset_to_point_data ({3})", header.header_size, vlrs_size, header.user_data_after_header_size, header.offset_to_point_data); return 1; } LASzip laszip=null; try { laszip=new LASzip(); } catch { error="could not alloc LASzip"; return 1; } 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; } #region create point's item pointers for(uint 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; } } #endregion uint laszip_vrl_payload_size=0; if(compress) { if(!laszip.setup(header.point_data_format, header.point_data_record_length, LASzip.COMPRESSOR_DEFAULT)) { error=string.Format("cannot compress point_data_format {0} with point_data_record_length {1}", header.point_data_format, header.point_data_record_length); return 1; } laszip.request_version(2); laszip_vrl_payload_size=34u+6u*laszip.num_items; } else { laszip.request_version(0); } #endregion #region open the file try { streamout=new FileStream(file_name, FileMode.Create, FileAccess.Write, FileShare.Read); } catch { error=string.Format("cannot open file '{0}'", file_name); return 1; } #endregion #region write the header variable after variable try { streamout.WriteByte((byte)'L'); streamout.WriteByte((byte)'A'); streamout.WriteByte((byte)'S'); streamout.WriteByte((byte)'F'); } catch { error="writing header.file_signature"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.file_source_ID), 0, 2); } catch { error="writing header.file_source_ID"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.global_encoding), 0, 2); } catch { error="writing header.global_encoding"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.project_ID_GUID_data_1), 0, 4); } catch { error="writing header.project_ID_GUID_data_1"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.project_ID_GUID_data_2), 0, 2); } catch { error="writing header.project_ID_GUID_data_2"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.project_ID_GUID_data_3), 0, 2); } catch { error="writing header.project_ID_GUID_data_3"; return 1; } try { streamout.Write(header.project_ID_GUID_data_4, 0, 8); } catch { error="writing header.project_ID_GUID_data_4"; return 1; } try { streamout.WriteByte(header.version_major); } catch { error="writing header.version_major"; return 1; } try { streamout.WriteByte(header.version_minor); } catch { error="writing header.version_minor"; return 1; } try { streamout.Write(header.system_identifier, 0, 32); } catch { error="writing header.system_identifier"; return 1; } byte[] generatingSoftware=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)); Array.Copy(generatingSoftware, header.generating_software, Math.Min(generatingSoftware.Length, 32)); try { streamout.Write(header.generating_software, 0, 32); } catch { error="writing header.generating_software"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.file_creation_day), 0, 2); } catch { error="writing header.file_creation_day"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.file_creation_year), 0, 2); } catch { error="writing header.file_creation_year"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.header_size), 0, 2); } catch { error="writing header.header_size"; return 1; } if(compress) header.offset_to_point_data+=(54+laszip_vrl_payload_size); try { streamout.Write(BitConverter.GetBytes(header.offset_to_point_data), 0, 4); } catch { error="writing header.offset_to_point_data"; return 1; } if(compress) { header.offset_to_point_data-=(54+laszip_vrl_payload_size); header.number_of_variable_length_records+=1; } try { streamout.Write(BitConverter.GetBytes(header.number_of_variable_length_records), 0, 4); } catch { error="writing header.number_of_variable_length_records"; return 1; } if(compress) { header.number_of_variable_length_records-=1; header.point_data_format|=128; } try { streamout.WriteByte(header.point_data_format); } catch { error="writing header.point_data_format"; return 1; } if(compress) header.point_data_format&=127; try { streamout.Write(BitConverter.GetBytes(header.point_data_record_length), 0, 2); } catch { error="writing header.point_data_record_length"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.number_of_point_records), 0, 4); } catch { error="writing header.number_of_point_records"; return 1; } for(uint i=0; i<5; i++) { try { streamout.Write(BitConverter.GetBytes(header.number_of_points_by_return[i]), 0, 4); } catch { error=string.Format("writing header.number_of_points_by_return {0}", i); return 1; } } try { streamout.Write(BitConverter.GetBytes(header.x_scale_factor), 0, 8); } catch { error="writing header.x_scale_factor"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.y_scale_factor), 0, 8); } catch { error="writing header.y_scale_factor"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.z_scale_factor), 0, 8); } catch { error="writing header.z_scale_factor"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.x_offset), 0, 8); } catch { error="writing header.x_offset"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.y_offset), 0, 8); } catch { error="writing header.y_offset"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.z_offset), 0, 8); } catch { error="writing header.z_offset"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.max_x), 0, 8); } catch { error="writing header.max_x"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.min_x), 0, 8); } catch { error="writing header.min_x"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.max_y), 0, 8); } catch { error="writing header.max_y"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.min_y), 0, 8); } catch { error="writing header.min_y"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.max_z), 0, 8); } catch { error="writing header.max_z"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.min_z), 0, 8); } catch { error="writing header.min_z"; return 1; } #region 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; } try { streamout.Write(BitConverter.GetBytes(header.start_of_waveform_data_packet_record), 0, 8); } catch { error="writing header.start_of_waveform_data_packet_record"; return 1; } header.user_data_in_header_size=header.header_size-235u; } else header.user_data_in_header_size=header.header_size-227u; #endregion #region 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; } try { streamout.Write(BitConverter.GetBytes(header.start_of_first_extended_variable_length_record), 0, 8); } catch { error="writing header.start_of_first_extended_variable_length_record"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.number_of_extended_variable_length_records), 0, 4); } catch { error="writing header.number_of_extended_variable_length_records"; return 1; } try { streamout.Write(BitConverter.GetBytes(header.extended_number_of_point_records), 0, 8); } catch { error="writing header.extended_number_of_point_records"; return 1; } for(uint i=0; i<15; i++) { try { streamout.Write(BitConverter.GetBytes(header.extended_number_of_points_by_return[i]), 0, 8); } catch { error=string.Format("writing header.extended_number_of_points_by_return[{0}]", i); return 1; } } header.user_data_in_header_size=header.header_size-375u; } #endregion #region write any number of user-defined bytes that might have been added to the header if(header.user_data_in_header_size!=0) { try { streamout.Write(header.user_data_in_header, 0, (int)header.user_data_in_header_size); } catch { error=string.Format("writing {0} bytes of data into header.user_data_in_header", header.user_data_in_header_size); return 1; } } #endregion #region write variable length records into the header if(header.number_of_variable_length_records!=0) { for(int i=0; i<header.number_of_variable_length_records; i++) { // write variable length records variable after variable (to avoid alignment issues) try { streamout.Write(BitConverter.GetBytes(header.vlrs[i].reserved), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].reserved", i); return 1; } try { streamout.Write(header.vlrs[i].user_id, 0, 16); } catch { error=string.Format("writing header.vlrs[{0}].user_id", i); return 1; } try { streamout.Write(BitConverter.GetBytes(header.vlrs[i].record_id), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].record_id", i); return 1; } try { streamout.Write(BitConverter.GetBytes(header.vlrs[i].record_length_after_header), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].record_length_after_header", i); return 1; } try { streamout.Write(header.vlrs[i].description, 0, 32); } catch { error=string.Format("writing header.vlrs[{0}].description", i); return 1; } // write data following the header of the variable length record if(header.vlrs[i].record_length_after_header!=0) { try { streamout.Write(header.vlrs[i].data, 0, header.vlrs[i].record_length_after_header); } catch { error=string.Format("writing {0} bytes of data into header.vlrs[{1}].data", header.vlrs[i].record_length_after_header, i); return 1; } } } } if(compress) { #region write the LASzip VLR header uint i=header.number_of_variable_length_records; ushort reserved=0xAABB; try { streamout.Write(BitConverter.GetBytes(reserved), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].reserved", i); return 1; } byte[] user_id1=Encoding.ASCII.GetBytes("laszip encoded"); byte[] user_id=new byte[16]; Array.Copy(user_id1, user_id, Math.Min(16, user_id1.Length)); try { streamout.Write(user_id, 0, 16); } catch { error=string.Format("writing header.vlrs[{0}].user_id", i); return 1; } ushort record_id=22204; try { streamout.Write(BitConverter.GetBytes(record_id), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].record_id", i); return 1; } ushort record_length_after_header=(ushort)laszip_vrl_payload_size; try { streamout.Write(BitConverter.GetBytes(record_length_after_header), 0, 2); } catch { error=string.Format("writing header.vlrs[{0}].record_length_after_header", i); return 1; } byte[] description1=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)); byte[] description=new byte[32]; try { streamout.Write(description, 0, 32); } catch { error=string.Format("writing header.vlrs[{0}].description", i); return 1; } // write 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 { streamout.Write(BitConverter.GetBytes(laszip.compressor), 0, 2); } catch { error=string.Format("writing compressor {0}", laszip.compressor); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.coder), 0, 2); } catch { error=string.Format("writing coder {0}", laszip.coder); return 1; } try { streamout.WriteByte(laszip.version_major); } catch { error=string.Format("writing version_major {0}", laszip.version_major); return 1; } try { streamout.WriteByte(laszip.version_minor); } catch { error=string.Format("writing version_minor {0}", laszip.version_minor); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.version_revision), 0, 2); } catch { error=string.Format("writing version_revision {0}", laszip.version_revision); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.options), 0, 4); } catch { error=string.Format("writing options {0}", laszip.options); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.chunk_size), 0, 4); } catch { error=string.Format("writing chunk_size {0}", laszip.chunk_size); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.number_of_special_evlrs), 0, 8); } catch { error=string.Format("writing number_of_special_evlrs {0}", laszip.number_of_special_evlrs); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.offset_to_special_evlrs), 0, 8); } catch { error=string.Format("writing offset_to_special_evlrs {0}", laszip.offset_to_special_evlrs); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.num_items), 0, 2); } catch { error=string.Format("writing num_items {0}", laszip.num_items); return 1; } for(uint j=0; j<laszip.num_items; j++) { ushort type=(ushort)laszip.items[j].type; try { streamout.Write(BitConverter.GetBytes(type), 0, 2); } catch { error=string.Format("writing type {0} of item {1}", laszip.items[j].type, j); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.items[j].size), 0, 2); } catch { error=string.Format("writing size {0} of item {1}", laszip.items[j].size, j); return 1; } try { streamout.Write(BitConverter.GetBytes(laszip.items[j].version), 0, 2); } catch { error=string.Format("writing version {0} of item {1}", laszip.items[j].version, j); return 1; } } #endregion } #endregion #region write any number of user-defined bytes that might have been added after the header if(header.user_data_after_header_size!=0) { try { streamout.Write(header.user_data_after_header, 0, (int)header.user_data_after_header_size); } catch { error=string.Format("writing {0} bytes of data into header.user_data_after_header", header.user_data_after_header_size); return 1; } } #endregion #endregion #region create the point writer try { writer=new LASwritePoint(); } catch { error="could not alloc LASwritePoint"; return 1; } if(!writer.setup(laszip.num_items, laszip.items, laszip)) { error="setup of LASwritePoint failed"; return 1; } if(!writer.init(streamout)) { error="init of LASwritePoint failed"; return 1; } #endregion // set the point number and point count npoints=header.number_of_point_records; p_count=0; } catch { error=string.Format("internal error in laszip_open_writer '{0}'", file_name); return 1; } error=null; return 0; }