Пример #1
0
        // should only be called *once*
        public bool setup(uint num_items, LASitem[] items, LASzip laszip = null)
        {
            // is laszip exists then we must use its items
            if (laszip != null)
            {
                if (num_items != laszip.num_items)
                {
                    return(false);
                }
                if (items != laszip.items)
                {
                    return(false);
                }
            }

            // create entropy decoder (if requested)
            dec = null;
            if (laszip != null && laszip.compressor != 0)
            {
                switch (laszip.coder)
                {
                case LASzip.CODER_ARITHMETIC: dec = new ArithmeticDecoder(); break;

                default: return(false);                        // entropy decoder not supported
                }
            }

            // initizalize the readers
            readers     = null;
            num_readers = num_items;

            // disable chunking
            chunk_size = uint.MaxValue;

            // always create the raw readers
            readers_raw = new LASreadItem[num_readers];
            for (int i = 0; i < num_readers; i++)
            {
                switch (items[i].type)
                {
                case LASitem.Type.POINT10: readers_raw[i] = new LASreadItemRaw_POINT10(); break;

                case LASitem.Type.GPSTIME11: readers_raw[i] = new LASreadItemRaw_GPSTIME11(); break;

                case LASitem.Type.RGB12: readers_raw[i] = new LASreadItemRaw_RGB12(); break;

                case LASitem.Type.WAVEPACKET13: readers_raw[i] = new LASreadItemRaw_WAVEPACKET13(); break;

                case LASitem.Type.BYTE: readers_raw[i] = new LASreadItemRaw_BYTE(items[i].size); break;

                case LASitem.Type.POINT14: readers_raw[i] = new LASreadItemRaw_POINT14(); break;

                case LASitem.Type.RGBNIR14: readers_raw[i] = new LASreadItemRaw_RGBNIR14(); break;

                default: return(false);
                }
                point_size += items[i].size;
            }

            if (dec != null)
            {
                readers_compressed = new LASreadItem[num_readers];

                // seeks with compressed data need a seek point
                for (int i = 0; i < num_readers; i++)
                {
                    switch (items[i].type)
                    {
                    case LASitem.Type.POINT10:
                        if (items[i].version == 1)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_POINT10_v1(dec);
                        }
                        else if (items[i].version == 2)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_POINT10_v2(dec);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.GPSTIME11:
                        if (items[i].version == 1)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_GPSTIME11_v1(dec);
                        }
                        else if (items[i].version == 2)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_GPSTIME11_v2(dec);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.RGB12:
                        if (items[i].version == 1)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_RGB12_v1(dec);
                        }
                        else if (items[i].version == 2)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_RGB12_v2(dec);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.WAVEPACKET13:
                        if (items[i].version == 1)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_WAVEPACKET13_v1(dec);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.BYTE:
                        seek_point.extra_bytes     = new byte[items[i].size];
                        seek_point.num_extra_bytes = items[i].size;
                        if (items[i].version == 1)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_BYTE_v1(dec, items[i].size);
                        }
                        else if (items[i].version == 2)
                        {
                            readers_compressed[i] = new LASreadItemCompressed_BYTE_v2(dec, items[i].size);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    default: return(false);
                    }
                }

                if (laszip.compressor == LASzip.COMPRESSOR_POINTWISE_CHUNKED)
                {
                    if (laszip.chunk_size != 0)
                    {
                        chunk_size = laszip.chunk_size;
                    }
                    number_chunks = uint.MaxValue;
                }
            }
            return(true);
        }
Пример #2
0
		// should only be called *once*
		public bool setup(uint num_items, LASitem[] items, LASzip laszip=null)
		{
			// is laszip exists then we must use its items
			if(laszip!=null)
			{
				if(num_items!=laszip.num_items) return false;
				if(items!=laszip.items) return false;
			}

			// create entropy encoder (if requested)
			enc=null;
			if(laszip!=null&&laszip.compressor!=0)
			{
				switch(laszip.coder)
				{
					case LASzip.CODER_ARITHMETIC: enc=new ArithmeticEncoder(); break;
					default: return false; // entropy decoder not supported
				}
			}

			// initizalize the writers
			writers=null;
			num_writers=num_items;

			// disable chunking
			chunk_size=uint.MaxValue;

			// always create the raw writers
			writers_raw=new LASwriteItem[num_writers];

			for(uint i=0; i<num_writers; i++)
			{
				switch(items[i].type)
				{
					case LASitem.Type.POINT10: writers_raw[i]=new LASwriteItemRaw_POINT10(); break;
					case LASitem.Type.GPSTIME11: writers_raw[i]=new LASwriteItemRaw_GPSTIME11(); break;
					case LASitem.Type.RGB12: writers_raw[i]=new LASwriteItemRaw_RGB12(); break;
					case LASitem.Type.WAVEPACKET13: writers_raw[i]=new LASwriteItemRaw_WAVEPACKET13(); break;
					case LASitem.Type.BYTE: writers_raw[i]=new LASwriteItemRaw_BYTE(items[i].size); break;
					case LASitem.Type.POINT14: writers_raw[i]=new LASwriteItemRaw_POINT14(); break;
					case LASitem.Type.RGBNIR14: writers_raw[i]=new LASwriteItemRaw_RGBNIR14(); break;
					default: return false;
				}
			}

			// if needed create the compressed writers and set versions
			if(enc!=null)
			{
				writers_compressed=new LASwriteItem[num_writers];

				for(uint i=0; i<num_writers; i++)
				{
					switch(items[i].type)
					{
						case LASitem.Type.POINT10:
							if(items[i].version==1) throw new NotSupportedException("Version 1 POINT10 is no longer supported, use version 2.");
							else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_POINT10_v2(enc);
							else return false;
							break;
						case LASitem.Type.GPSTIME11:
							if(items[i].version==1) throw new NotSupportedException("Version 1 GPSTIME11 is no longer supported, use version 2.");
							else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_GPSTIME11_v2(enc);
							else return false;
							break;
						case LASitem.Type.RGB12:
							if(items[i].version==1) throw new NotSupportedException("Version 1 RGB12 is no longer supported, use version 2.");
							else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_RGB12_v2(enc);
							else return false;
							break;
						case LASitem.Type.WAVEPACKET13:
							if(items[i].version==1) writers_compressed[i]=new LASwriteItemCompressed_WAVEPACKET13_v1(enc);
							else return false;
							break;
						case LASitem.Type.BYTE:
							if(items[i].version==1) throw new NotSupportedException("Version 1 BYTE is no longer supported, use version 2.");
							else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_BYTE_v2(enc, items[i].size);
							else return false;
							break;
						default: return false;
					}
				}

				if(laszip.compressor==LASzip.COMPRESSOR_POINTWISE_CHUNKED)
				{
					if(laszip.chunk_size!=0) chunk_size=laszip.chunk_size;
					chunk_count=0;
					init_chunking=true;
				}
			}

			return true;
		}
Пример #3
0
		// should only be called *once*
		public bool setup(uint num_items, LASitem[] items, LASzip laszip=null)
		{
			// is laszip exists then we must use its items
			if(laszip!=null)
			{
				if(num_items!=laszip.num_items) return false;
				if(items!=laszip.items) return false;
			}

			// create entropy decoder (if requested)
			dec=null;
			if(laszip!=null&&laszip.compressor!=0)
			{
				switch(laszip.coder)
				{
					case LASzip.CODER_ARITHMETIC: dec=new ArithmeticDecoder(); break;
					default: return false; // entropy decoder not supported
				}
			}

			// initizalize the readers
			readers=null;
			num_readers=num_items;

			// disable chunking
			chunk_size=uint.MaxValue;

			// always create the raw readers
			readers_raw=new LASreadItem[num_readers];
			for(int i=0; i<num_readers; i++)
			{
				switch(items[i].type)
				{
					case LASitem.Type.POINT10: readers_raw[i]=new LASreadItemRaw_POINT10(); break;
					case LASitem.Type.GPSTIME11: readers_raw[i]=new LASreadItemRaw_GPSTIME11(); break;
					case LASitem.Type.RGB12: readers_raw[i]=new LASreadItemRaw_RGB12(); break;
					case LASitem.Type.WAVEPACKET13: readers_raw[i]=new LASreadItemRaw_WAVEPACKET13(); break;
					case LASitem.Type.BYTE: readers_raw[i]=new LASreadItemRaw_BYTE(items[i].size); break;
					case LASitem.Type.POINT14: readers_raw[i]=new LASreadItemRaw_POINT14(); break;
					case LASitem.Type.RGBNIR14: readers_raw[i]=new LASreadItemRaw_RGBNIR14(); break;
					default: return false;
				}
				point_size+=items[i].size;
			}

			if(dec!=null)
			{
				readers_compressed=new LASreadItem[num_readers];

				// seeks with compressed data need a seek point
				for(int i=0; i<num_readers; i++)
				{
					switch(items[i].type)
					{
						case LASitem.Type.POINT10:
							if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_POINT10_v1(dec);
							else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_POINT10_v2(dec);
							else return false;
							break;
						case LASitem.Type.GPSTIME11:
							if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_GPSTIME11_v1(dec);
							else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_GPSTIME11_v2(dec);
							else return false;
							break;
						case LASitem.Type.RGB12:
							if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_RGB12_v1(dec);
							else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_RGB12_v2(dec);
							else return false;
							break;
						case LASitem.Type.WAVEPACKET13:
							if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_WAVEPACKET13_v1(dec);
							else return false;
							break;
						case LASitem.Type.BYTE:
							seek_point.extra_bytes=new byte[items[i].size];
							seek_point.num_extra_bytes=items[i].size;
							if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_BYTE_v1(dec, items[i].size);
							else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_BYTE_v2(dec, items[i].size);
							else return false;
							break;
						default: return false;
					}
				}

				if(laszip.compressor==LASzip.COMPRESSOR_POINTWISE_CHUNKED)
				{
					if(laszip.chunk_size!=0) chunk_size=laszip.chunk_size;
					number_chunks=uint.MaxValue;
				}
			}
			return true;
		}
Пример #4
0
        // should only be called *once*
        public bool setup(uint num_items, LASitem[] items, LASzip laszip = null)
        {
            // is laszip exists then we must use its items
            if (laszip != null)
            {
                if (num_items != laszip.num_items)
                {
                    return(false);
                }
                if (items != laszip.items)
                {
                    return(false);
                }
            }

            // create entropy encoder (if requested)
            enc = null;
            if (laszip != null && laszip.compressor != 0)
            {
                switch (laszip.coder)
                {
                case LASzip.CODER_ARITHMETIC: enc = new ArithmeticEncoder(); break;

                default: return(false);                        // entropy decoder not supported
                }
            }

            // initizalize the writers
            writers     = null;
            num_writers = num_items;

            // disable chunking
            chunk_size = uint.MaxValue;

            // always create the raw writers
            writers_raw = new LASwriteItem[num_writers];

            for (uint i = 0; i < num_writers; i++)
            {
                switch (items[i].type)
                {
                case LASitem.Type.POINT10: writers_raw[i] = new LASwriteItemRaw_POINT10(); break;

                case LASitem.Type.GPSTIME11: writers_raw[i] = new LASwriteItemRaw_GPSTIME11(); break;

                case LASitem.Type.RGB12: writers_raw[i] = new LASwriteItemRaw_RGB12(); break;

                case LASitem.Type.WAVEPACKET13: writers_raw[i] = new LASwriteItemRaw_WAVEPACKET13(); break;

                case LASitem.Type.BYTE: writers_raw[i] = new LASwriteItemRaw_BYTE(items[i].size); break;

                case LASitem.Type.POINT14: writers_raw[i] = new LASwriteItemRaw_POINT14(); break;

                case LASitem.Type.RGBNIR14: writers_raw[i] = new LASwriteItemRaw_RGBNIR14(); break;

                default: return(false);
                }
            }

            // if needed create the compressed writers and set versions
            if (enc != null)
            {
                writers_compressed = new LASwriteItem[num_writers];

                for (uint i = 0; i < num_writers; i++)
                {
                    switch (items[i].type)
                    {
                    case LASitem.Type.POINT10:
                        if (items[i].version == 1)
                        {
                            throw new NotSupportedException("Version 1 POINT10 is no longer supported, use version 2.");
                        }
                        else if (items[i].version == 2)
                        {
                            writers_compressed[i] = new LASwriteItemCompressed_POINT10_v2(enc);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.GPSTIME11:
                        if (items[i].version == 1)
                        {
                            throw new NotSupportedException("Version 1 GPSTIME11 is no longer supported, use version 2.");
                        }
                        else if (items[i].version == 2)
                        {
                            writers_compressed[i] = new LASwriteItemCompressed_GPSTIME11_v2(enc);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.RGB12:
                        if (items[i].version == 1)
                        {
                            throw new NotSupportedException("Version 1 RGB12 is no longer supported, use version 2.");
                        }
                        else if (items[i].version == 2)
                        {
                            writers_compressed[i] = new LASwriteItemCompressed_RGB12_v2(enc);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.WAVEPACKET13:
                        if (items[i].version == 1)
                        {
                            writers_compressed[i] = new LASwriteItemCompressed_WAVEPACKET13_v1(enc);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    case LASitem.Type.BYTE:
                        if (items[i].version == 1)
                        {
                            throw new NotSupportedException("Version 1 BYTE is no longer supported, use version 2.");
                        }
                        else if (items[i].version == 2)
                        {
                            writers_compressed[i] = new LASwriteItemCompressed_BYTE_v2(enc, items[i].size);
                        }
                        else
                        {
                            return(false);
                        }
                        break;

                    default: return(false);
                    }
                }

                if (laszip.compressor == LASzip.COMPRESSOR_POINTWISE_CHUNKED)
                {
                    if (laszip.chunk_size != 0)
                    {
                        chunk_size = laszip.chunk_size;
                    }
                    chunk_count   = 0;
                    init_chunking = true;
                }
            }

            return(true);
        }
Пример #5
0
		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;
		}
Пример #6
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;
		}