Exemple #1
0
		public bool check_item(LASitem item)
		{
			switch(item.type)
			{
				case LASitem.Type.POINT10:
					if(item.size!=20) return return_error("POINT10 has size != 20");
					if(item.version>2) return return_error("POINT10 has version > 2");
					break;
				case LASitem.Type.GPSTIME11:
					if(item.size!=8) return return_error("GPSTIME11 has size != 8");
					if(item.version>2) return return_error("GPSTIME11 has version > 2");
					break;
				case LASitem.Type.RGB12:
					if(item.size!=6) return return_error("RGB12 has size != 6");
					if(item.version>2) return return_error("RGB12 has version > 2");
					break;
				case LASitem.Type.WAVEPACKET13:
					if(item.size!=29) return return_error("WAVEPACKET13 has size != 29");
					if(item.version>1) return return_error("WAVEPACKET13 has version > 1");
					break;
				case LASitem.Type.BYTE:
					if(item.size<1) return return_error("BYTE has size < 1");
					if(item.version>2) return return_error("BYTE has version > 2");
					break;
				case LASitem.Type.POINT14:
					if(item.size!=30) return return_error("POINT14 has size != 30");
					if(item.version>0) return return_error("POINT14 has version > 0");
					break;
				case LASitem.Type.RGBNIR14:
					if(item.size!=8) return return_error("RGBNIR14 has size != 8");
					if(item.version>0) return return_error("RGBNIR14 has version > 0");
					break;
				default:
					if(true)
						return return_error(string.Format("item unknown ({0},{1},{2})", item.type, item.size, item.version));
			}
			return true;
		}
Exemple #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;
		}
Exemple #3
0
		public unsafe bool unpack(byte[] bytes, int num)
		{
			// check input
			if(num<34) return return_error("too few bytes to unpack");
			if(((num-34)%6)!=0) return return_error("wrong number bytes to unpack");
			if(((num-34)/6)==0) return return_error("zero items to unpack");
			num_items=(ushort)((num-34)/6);

			// create item list
			items=new LASitem[num_items];

			// do the unpacking
			ushort i;
			fixed(byte* pBytes=bytes)
			{
				byte* b=pBytes;
				compressor=*((ushort*)b);
				b+=2;
				coder=*((ushort*)b);
				b+=2;
				version_major=*b;
				b+=1;
				version_minor=*b;
				b+=1;
				version_revision=*((ushort*)b);
				b+=2;
				options=*((uint*)b);
				b+=4;
				chunk_size=*((uint*)b);
				b+=4;
				number_of_special_evlrs=*((long*)b);
				b+=8;
				offset_to_special_evlrs=*((long*)b);
				b+=8;
				num_items=*((ushort*)b);
				b+=2;
				for(i=0; i<num_items; i++)
				{
					items[i].type=(LASitem.Type)(int)*((ushort*)b);
					b+=2;
					items[i].size=*((ushort*)b);
					b+=2;
					items[i].version=*((ushort*)b);
					b+=2;
				}
				Debug.Assert((pBytes+num)==b);

				// check if we support the contents
				for(i=0; i<num_items; i++)
				{
					if(!check_item(items[i])) return false;
				}
				return true;
			}
		}
Exemple #4
0
		public bool setup(ushort num_items, LASitem[] items, ushort compressor)
		{
			// check input
			if(!check_compressor(compressor)) return false;
			if(!check_items(num_items, items)) return false;

			// setup compressor
			this.compressor=compressor;
			if(this.compressor==COMPRESSOR_POINTWISE_CHUNKED)
			{
				if(chunk_size==0) chunk_size=CHUNK_SIZE_DEFAULT;
			}

			// prepare items
			this.num_items=0;
			this.items=null;
			this.num_items=num_items;
			this.items=new LASitem[num_items];

			// setup items
			for(int i=0; i<num_items; i++)
			{
				this.items[i]=items[i];
			}

			return true;
		}
Exemple #5
0
		// go back and forth between item array and point type & size
		public bool setup(out ushort num_items, out LASitem[] items, byte point_type, ushort point_size, ushort compressor=COMPRESSOR_NONE)
		{
			num_items=0;
			items=null;

			bool have_point14=false;
			bool have_gps_time=false;
			bool have_rgb=false;
			bool have_nir=false;
			bool have_wavepacket=false;
			int extra_bytes_number=0;

			// switch over the point types we know
			switch(point_type)
			{
				case 0:
					extra_bytes_number=(int)point_size-20;
					break;
				case 1:
					have_gps_time=true;
					extra_bytes_number=(int)point_size-28;
					break;
				case 2:
					have_rgb=true;
					extra_bytes_number=(int)point_size-26;
					break;
				case 3:
					have_gps_time=true;
					have_rgb=true;
					extra_bytes_number=(int)point_size-34;
					break;
				case 4:
					have_gps_time=true;
					have_wavepacket=true;
					extra_bytes_number=(int)point_size-57;
					break;
				case 5:
					have_gps_time=true;
					have_rgb=true;
					have_wavepacket=true;
					extra_bytes_number=(int)point_size-63;
					break;
				case 6:
					have_point14=true;
					extra_bytes_number=(int)point_size-30;
					break;
				case 7:
					have_point14=true;
					have_rgb=true;
					extra_bytes_number=(int)point_size-36;
					break;
				case 8:
					have_point14=true;
					have_rgb=true;
					have_nir=true;
					extra_bytes_number=(int)point_size-38;
					break;
				case 9:
					have_point14=true;
					have_wavepacket=true;
					extra_bytes_number=(int)point_size-59;
					break;
				case 10:
					have_point14=true;
					have_rgb=true;
					have_nir=true;
					have_wavepacket=true;
					extra_bytes_number=(int)point_size-67;
					break;
				default:
					if(true)
						return return_error(string.Format("point type {0} unknown", point_type));
			}

			if(extra_bytes_number<0)
			{
				Console.Error.WriteLine("WARNING: point size {0} too small by {1} bytes for point type {2}. assuming point_size of {3}", point_size, -extra_bytes_number, point_type, point_size-extra_bytes_number);
				extra_bytes_number=0;
			}

			// create item description

			num_items=(ushort)(1+(have_gps_time?1:0)+(have_rgb?1:0)+(have_wavepacket?1:0)+(extra_bytes_number!=0?1:0));
			items=new LASitem[num_items];

			ushort i=1;
			if(have_point14)
			{
				items[0]=new LASitem();
				items[0].type=LASitem.Type.POINT14;
				items[0].size=30;
				items[0].version=0;
			}
			else
			{
				items[0]=new LASitem();
				items[0].type=LASitem.Type.POINT10;
				items[0].size=20;
				items[0].version=0;
			}
			if(have_gps_time)
			{
				items[i]=new LASitem();
				items[i].type=LASitem.Type.GPSTIME11;
				items[i].size=8;
				items[i].version=0;
				i++;
			}
			if(have_rgb)
			{
				items[i]=new LASitem();
				if(have_nir)
				{
					items[i].type=LASitem.Type.RGBNIR14;
					items[i].size=8;
					items[i].version=0;
				}
				else
				{
					items[i].type=LASitem.Type.RGB12;
					items[i].size=6;
					items[i].version=0;
				}
				i++;
			}
			if(have_wavepacket)
			{
				items[i]=new LASitem();
				items[i].type=LASitem.Type.WAVEPACKET13;
				items[i].size=29;
				items[i].version=0;
				i++;
			}
			if(extra_bytes_number!=0)
			{
				items[i]=new LASitem();
				items[i].type=LASitem.Type.BYTE;
				items[i].size=(ushort)extra_bytes_number;
				items[i].version=0;
				i++;
			}
			if(compressor!=0) request_version(2);
			Debug.Assert(i==num_items);
			return true;
		}
Exemple #6
0
		public bool is_standard(ushort num_items, LASitem[] items, out byte point_type, out ushort record_length)
		{
			// this is always true
			point_type=127;
			record_length=0;

			if(items==null) return return_error("LASitem array is zero");

			for(int i=0; i<num_items; i++) record_length+=items[i].size;

			// the minimal number of items is 1
			if(num_items<1) return return_error("less than one LASitem entries");
			// the maximal number of items is 5
			if(num_items>5) return return_error("more than five LASitem entries");

			if(items[0].is_type(LASitem.Type.POINT10))
			{
				// consider all the POINT10 combinations
				if(num_items==1)
				{
					point_type=0;
					Debug.Assert(record_length==20);
					return true;
				}
				else
				{
					if(items[1].is_type(LASitem.Type.GPSTIME11))
					{
						if(num_items==2)
						{
							point_type=1;
							Debug.Assert(record_length==28);
							return true;
						}
						else
						{
							if(items[2].is_type(LASitem.Type.RGB12))
							{
								if(num_items==3)
								{
									point_type=3;
									Debug.Assert(record_length==34);
									return true;
								}
								else
								{
									if(items[3].is_type(LASitem.Type.WAVEPACKET13))
									{
										if(num_items==4)
										{
											point_type=5;
											Debug.Assert(record_length==63);
											return true;
										}
										else
										{
											if(items[4].is_type(LASitem.Type.BYTE))
											{
												if(num_items==5)
												{
													point_type=5;
													Debug.Assert(record_length==(63+items[4].size));
													return true;
												}
											}
										}
									}
									else if(items[3].is_type(LASitem.Type.BYTE))
									{
										if(num_items==4)
										{
											point_type=3;
											Debug.Assert(record_length==(34+items[3].size));
											return true;
										}
									}
								}
							}
							else if(items[2].is_type(LASitem.Type.WAVEPACKET13))
							{
								if(num_items==3)
								{
									point_type=4;
									Debug.Assert(record_length==57);
									return true;
								}
								else
								{
									if(items[3].is_type(LASitem.Type.BYTE))
									{
										if(num_items==4)
										{
											point_type=4;
											Debug.Assert(record_length==(57+items[3].size));
											return true;
										}
									}
								}
							}
							else if(items[2].is_type(LASitem.Type.BYTE))
							{
								if(num_items==3)
								{
									point_type=1;
									Debug.Assert(record_length==(28+items[2].size));
									return true;
								}
							}
						}
					}
					else if(items[1].is_type(LASitem.Type.RGB12))
					{
						if(num_items==2)
						{
							point_type=2;
							Debug.Assert(record_length==26);
							return true;
						}
						else
						{
							if(items[2].is_type(LASitem.Type.BYTE))
							{
								if(num_items==3)
								{
									point_type=2;
									Debug.Assert(record_length==(26+items[2].size));
									return true;
								}
							}
						}
					}
					else if(items[1].is_type(LASitem.Type.BYTE))
					{
						if(num_items==2)
						{
							point_type=0;
							Debug.Assert(record_length==(20+items[1].size));
							return true;
						}
					}
				}
			}
			else if(items[0].is_type(LASitem.Type.POINT14))
			{
				// consider all the POINT14 combinations
				if(num_items==1)
				{
					point_type=6;
					Debug.Assert(record_length==30);
					return true;
				}
				else
				{
					if(items[1].is_type(LASitem.Type.RGB12))
					{
						if(num_items==2)
						{
							point_type=7;
							Debug.Assert(record_length==36);
							return true;
						}
						else
						{
							if(items[2].is_type(LASitem.Type.BYTE))
							{
								if(num_items==3)
								{
									point_type=7;
									Debug.Assert(record_length==(36+items[2].size));
									return true;
								}
							}
						}
					}
					else if(items[1].is_type(LASitem.Type.RGBNIR14))
					{
						if(num_items==2)
						{
							point_type=8;
							Debug.Assert(record_length==38);
							return true;
						}
						else
						{
							if(items[2].is_type(LASitem.Type.WAVEPACKET13))
							{
								if(num_items==3)
								{
									point_type=10;
									Debug.Assert(record_length==67);
									return true;
								}
								else
								{
									if(items[3].is_type(LASitem.Type.BYTE))
									{
										if(num_items==4)
										{
											point_type=10;
											Debug.Assert(record_length==(67+items[3].size));
											return true;
										}
									}
								}
							}
							else if(items[2].is_type(LASitem.Type.BYTE))
							{
								if(num_items==3)
								{
									point_type=8;
									Debug.Assert(record_length==(38+items[2].size));
									return true;
								}
							}
						}
					}
					else if(items[1].is_type(LASitem.Type.WAVEPACKET13))
					{
						if(num_items==2)
						{
							point_type=9;
							Debug.Assert(record_length==59);
							return true;
						}
						else
						{
							if(items[2].is_type(LASitem.Type.BYTE))
							{
								if(num_items==3)
								{
									point_type=9;
									Debug.Assert(record_length==(59+items[2].size));
									return true;
								}
							}
						}
					}
					else if(items[1].is_type(LASitem.Type.BYTE))
					{
						if(num_items==2)
						{
							point_type=6;
							Debug.Assert(record_length==(30+items[1].size));
							return true;
						}
					}
				}
			}
			else
			{
				return_error("first LASitem is neither POINT10 nor POINT14");
			}
			return return_error("LASitem array does not match LAS specification 1.4");
		}
Exemple #7
0
		public bool check_items(ushort num_items, LASitem[] items)
		{
			if(num_items==0) return return_error("number of items cannot be zero");
			if(items==null) return return_error("items pointer cannot be NULL");
			for(int i=0; i<num_items; i++)
			{
				if(!check_item(items[i])) return false;
			}
			return true;
		}
Exemple #8
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;
		}
Exemple #9
0
        public bool check_item(LASitem item)
        {
            switch (item.type)
            {
            case LASitem.Type.POINT10:
                if (item.size != 20)
                {
                    return(return_error("POINT10 has size != 20"));
                }
                if (item.version > 2)
                {
                    return(return_error("POINT10 has version > 2"));
                }
                break;

            case LASitem.Type.GPSTIME11:
                if (item.size != 8)
                {
                    return(return_error("GPSTIME11 has size != 8"));
                }
                if (item.version > 2)
                {
                    return(return_error("GPSTIME11 has version > 2"));
                }
                break;

            case LASitem.Type.RGB12:
                if (item.size != 6)
                {
                    return(return_error("RGB12 has size != 6"));
                }
                if (item.version > 2)
                {
                    return(return_error("RGB12 has version > 2"));
                }
                break;

            case LASitem.Type.WAVEPACKET13:
                if (item.size != 29)
                {
                    return(return_error("WAVEPACKET13 has size != 29"));
                }
                if (item.version > 1)
                {
                    return(return_error("WAVEPACKET13 has version > 1"));
                }
                break;

            case LASitem.Type.BYTE:
                if (item.size < 1)
                {
                    return(return_error("BYTE has size < 1"));
                }
                if (item.version > 2)
                {
                    return(return_error("BYTE has version > 2"));
                }
                break;

            case LASitem.Type.POINT14:
                if (item.size != 30)
                {
                    return(return_error("POINT14 has size != 30"));
                }
                if (item.version > 0)
                {
                    return(return_error("POINT14 has version > 0"));
                }
                break;

            case LASitem.Type.RGBNIR14:
                if (item.size != 8)
                {
                    return(return_error("RGBNIR14 has size != 8"));
                }
                if (item.version > 0)
                {
                    return(return_error("RGBNIR14 has version > 0"));
                }
                break;

            default:
                if (true)
                {
                    return(return_error(string.Format("item unknown ({0},{1},{2})", item.type, item.size, item.version)));
                }
            }
            return(true);
        }
Exemple #10
0
        public unsafe bool unpack(byte[] bytes, int num)
        {
            // check input
            if (num < 34)
            {
                return(return_error("too few bytes to unpack"));
            }
            if (((num - 34) % 6) != 0)
            {
                return(return_error("wrong number bytes to unpack"));
            }
            if (((num - 34) / 6) == 0)
            {
                return(return_error("zero items to unpack"));
            }
            num_items = (ushort)((num - 34) / 6);

            // create item list
            items = new LASitem[num_items];

            // do the unpacking
            ushort i;

            fixed(byte *pBytes = bytes)
            {
                byte *b = pBytes;

                compressor              = *((ushort *)b);
                b                      += 2;
                coder                   = *((ushort *)b);
                b                      += 2;
                version_major           = *b;
                b                      += 1;
                version_minor           = *b;
                b                      += 1;
                version_revision        = *((ushort *)b);
                b                      += 2;
                options                 = *((uint *)b);
                b                      += 4;
                chunk_size              = *((uint *)b);
                b                      += 4;
                number_of_special_evlrs = *((long *)b);
                b                      += 8;
                offset_to_special_evlrs = *((long *)b);
                b                      += 8;
                num_items               = *((ushort *)b);
                b                      += 2;
                for (i = 0; i < num_items; i++)
                {
                    items[i].type    = (LASitem.Type)(int) * ((ushort *)b);
                    b               += 2;
                    items[i].size    = *((ushort *)b);
                    b               += 2;
                    items[i].version = *((ushort *)b);
                    b               += 2;
                }
                Debug.Assert((pBytes + num) == b);

                // check if we support the contents
                for (i = 0; i < num_items; i++)
                {
                    if (!check_item(items[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }
        }
Exemple #11
0
        // go back and forth between item array and point type & size
        public bool setup(out ushort num_items, out LASitem[] items, byte point_type, ushort point_size, ushort compressor = COMPRESSOR_NONE)
        {
            num_items = 0;
            items     = null;

            bool have_point14       = false;
            bool have_gps_time      = false;
            bool have_rgb           = false;
            bool have_nir           = false;
            bool have_wavepacket    = false;
            int  extra_bytes_number = 0;

            // switch over the point types we know
            switch (point_type)
            {
            case 0:
                extra_bytes_number = (int)point_size - 20;
                break;

            case 1:
                have_gps_time      = true;
                extra_bytes_number = (int)point_size - 28;
                break;

            case 2:
                have_rgb           = true;
                extra_bytes_number = (int)point_size - 26;
                break;

            case 3:
                have_gps_time      = true;
                have_rgb           = true;
                extra_bytes_number = (int)point_size - 34;
                break;

            case 4:
                have_gps_time      = true;
                have_wavepacket    = true;
                extra_bytes_number = (int)point_size - 57;
                break;

            case 5:
                have_gps_time      = true;
                have_rgb           = true;
                have_wavepacket    = true;
                extra_bytes_number = (int)point_size - 63;
                break;

            case 6:
                have_point14       = true;
                extra_bytes_number = (int)point_size - 30;
                break;

            case 7:
                have_point14       = true;
                have_rgb           = true;
                extra_bytes_number = (int)point_size - 36;
                break;

            case 8:
                have_point14       = true;
                have_rgb           = true;
                have_nir           = true;
                extra_bytes_number = (int)point_size - 38;
                break;

            case 9:
                have_point14       = true;
                have_wavepacket    = true;
                extra_bytes_number = (int)point_size - 59;
                break;

            case 10:
                have_point14       = true;
                have_rgb           = true;
                have_nir           = true;
                have_wavepacket    = true;
                extra_bytes_number = (int)point_size - 67;
                break;

            default:
                if (true)
                {
                    return(return_error(string.Format("point type {0} unknown", point_type)));
                }
            }

            if (extra_bytes_number < 0)
            {
                Console.Error.WriteLine("WARNING: point size {0} too small by {1} bytes for point type {2}. assuming point_size of {3}", point_size, -extra_bytes_number, point_type, point_size - extra_bytes_number);
                extra_bytes_number = 0;
            }

            // create item description

            num_items = (ushort)(1 + (have_gps_time?1:0) + (have_rgb?1:0) + (have_wavepacket?1:0) + (extra_bytes_number != 0?1:0));
            items     = new LASitem[num_items];

            ushort i = 1;

            if (have_point14)
            {
                items[0]         = new LASitem();
                items[0].type    = LASitem.Type.POINT14;
                items[0].size    = 30;
                items[0].version = 0;
            }
            else
            {
                items[0]         = new LASitem();
                items[0].type    = LASitem.Type.POINT10;
                items[0].size    = 20;
                items[0].version = 0;
            }
            if (have_gps_time)
            {
                items[i]         = new LASitem();
                items[i].type    = LASitem.Type.GPSTIME11;
                items[i].size    = 8;
                items[i].version = 0;
                i++;
            }
            if (have_rgb)
            {
                items[i] = new LASitem();
                if (have_nir)
                {
                    items[i].type    = LASitem.Type.RGBNIR14;
                    items[i].size    = 8;
                    items[i].version = 0;
                }
                else
                {
                    items[i].type    = LASitem.Type.RGB12;
                    items[i].size    = 6;
                    items[i].version = 0;
                }
                i++;
            }
            if (have_wavepacket)
            {
                items[i]         = new LASitem();
                items[i].type    = LASitem.Type.WAVEPACKET13;
                items[i].size    = 29;
                items[i].version = 0;
                i++;
            }
            if (extra_bytes_number != 0)
            {
                items[i]         = new LASitem();
                items[i].type    = LASitem.Type.BYTE;
                items[i].size    = (ushort)extra_bytes_number;
                items[i].version = 0;
                i++;
            }
            if (compressor != 0)
            {
                request_version(2);
            }
            Debug.Assert(i == num_items);
            return(true);
        }