mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-10 11:02:31 +02:00
366 lines
13 KiB
ObjectPascal
366 lines
13 KiB
ObjectPascal
{
|
|
Pascal laszip tool, capable of compressing/uncompressing
|
|
LIDAR files from standard *.las to *.las.lz / *.laz format.
|
|
|
|
copyright (C) 2012 felipemonteiro.carvalho@gmail.com
|
|
|
|
This software is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
}
|
|
program laszip;
|
|
|
|
uses SysUtils, Classes;
|
|
{#include <time.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "lasreader.hpp"
|
|
#include "laswriter.hpp"}
|
|
|
|
procedure ExitProgram(AWait: Boolean);
|
|
var
|
|
Str: string;
|
|
begin
|
|
if AWait then
|
|
begin
|
|
WriteLn('<press ENTER>');
|
|
Read(Str);
|
|
end;
|
|
Halt(1);
|
|
end;
|
|
|
|
procedure Usage(AWait: Boolean = True);
|
|
begin
|
|
WriteLn('usage:');
|
|
WriteLn('laszip -i lidar.las');
|
|
WriteLn('laszip -i lidar.laz');
|
|
WriteLn('laszip -i lidar.las -o lidar_compressed.laz');
|
|
WriteLn('laszip -h');
|
|
ExitProgram(AWait);
|
|
end;
|
|
|
|
//static double taketime()
|
|
// return (double)(clock())/CLOCKS_PER_SEC;
|
|
|
|
var
|
|
i: Integer;
|
|
dry: Boolean = false;
|
|
verbose: Boolean = false;
|
|
file_name_in, file_name_out: string;
|
|
range: Boolean = true;
|
|
start_time: Double = 0;
|
|
file_in, file_out: TFileStream;
|
|
begin
|
|
if ParamCount = 1 then
|
|
begin
|
|
WriteLn('enter input file: ');
|
|
ReadLn(file_name_in);
|
|
WriteLn('enter output file: ');
|
|
ReadLn(file_name_out);
|
|
end;
|
|
|
|
i := 1;
|
|
while i < ParamCount do
|
|
begin
|
|
if ParamStr(i) = '-dry' then
|
|
begin
|
|
dry := true;
|
|
end
|
|
else if ParamStr(i) = '-verbose' then
|
|
begin
|
|
verbose := true;
|
|
end
|
|
else if ParamStr(i) = '-range' then
|
|
begin
|
|
range = true;
|
|
end
|
|
(*else if (strcmp(argv[i],"-arithmetic") == 0 || strcmp(argv[i],"-arith") == 0)
|
|
begin
|
|
range = false;
|
|
end*)
|
|
else if ParamStr(i) = '-h' then
|
|
begin
|
|
usage();
|
|
end
|
|
else if ParamStr(i) = '-i' then
|
|
begin
|
|
Inc(i);
|
|
file_name_in := ParamStr(i);
|
|
end
|
|
else if ParamStr(i) = '-o' then
|
|
begin
|
|
Inc(i);
|
|
file_name_out = ParamStr(i);
|
|
end
|
|
else
|
|
begin
|
|
WriteLn(Format('cannot understand argument "%s"', [ParamStr(i)]));
|
|
usage();
|
|
end;
|
|
|
|
Inc(i);
|
|
end;
|
|
|
|
// open input file
|
|
|
|
if file_name_in <> '' then
|
|
begin
|
|
try
|
|
file_in := TFileStream.Create(file_name_in, fmRead);
|
|
except
|
|
WriteLn(Format('ERROR: could not open "%s"', [file_name_in]));
|
|
byebye(ParamCount=1);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
WriteLn('ERROR: no input specified');
|
|
usage(ParamCount=1);
|
|
end;
|
|
|
|
LASreader* lasreader = new LASreader();
|
|
|
|
if (!lasreader->open(file_in))
|
|
{
|
|
fprintf(stderr, "ERROR: could not open lasreader\n");
|
|
byebye(argc==1);
|
|
}
|
|
|
|
// maybe only a read pass
|
|
|
|
if (dry) then
|
|
begin
|
|
(* LASpoint point_min;
|
|
LASpoint point_max;
|
|
double gps_time_min = 0;
|
|
double gps_time_max = 0;
|
|
short rgb_min[3] = {0,0,0};
|
|
short rgb_max[3] = {0,0,0};
|
|
|
|
start_time = taketime();
|
|
|
|
if (verbose)
|
|
{
|
|
lasreader->read_point();
|
|
point_min = lasreader->point;
|
|
point_max = lasreader->point;
|
|
if (lasreader->points_have_gps_time)
|
|
{
|
|
gps_time_min = lasreader->gps_time;
|
|
gps_time_max = lasreader->gps_time;
|
|
}
|
|
if (lasreader->points_have_rgb)
|
|
{
|
|
rgb_min[0] = lasreader->rgb[0];
|
|
rgb_min[1] = lasreader->rgb[1];
|
|
rgb_min[2] = lasreader->rgb[2];
|
|
rgb_max[0] = lasreader->rgb[0];
|
|
rgb_max[1] = lasreader->rgb[1];
|
|
rgb_max[2] = lasreader->rgb[2];
|
|
}
|
|
while (lasreader->read_point())
|
|
{
|
|
if (lasreader->point.x < point_min.x) point_min.x = lasreader->point.x;
|
|
else if (lasreader->point.x > point_max.x) point_max.x = lasreader->point.x;
|
|
if (lasreader->point.y < point_min.y) point_min.y = lasreader->point.y;
|
|
else if (lasreader->point.y > point_max.y) point_max.y = lasreader->point.y;
|
|
if (lasreader->point.z < point_min.z) point_min.z = lasreader->point.z;
|
|
else if (lasreader->point.z > point_max.z) point_max.z = lasreader->point.z;
|
|
if (lasreader->point.intensity < point_min.intensity) point_min.intensity = lasreader->point.intensity;
|
|
else if (lasreader->point.intensity > point_max.intensity) point_max.intensity = lasreader->point.intensity;
|
|
if (lasreader->point.edge_of_flight_line < point_min.edge_of_flight_line) point_min.edge_of_flight_line = lasreader->point.edge_of_flight_line;
|
|
else if (lasreader->point.edge_of_flight_line > point_max.edge_of_flight_line) point_max.edge_of_flight_line = lasreader->point.edge_of_flight_line;
|
|
if (lasreader->point.scan_direction_flag < point_min.scan_direction_flag) point_min.scan_direction_flag = lasreader->point.scan_direction_flag;
|
|
else if (lasreader->point.scan_direction_flag > point_max.scan_direction_flag) point_max.scan_direction_flag = lasreader->point.scan_direction_flag;
|
|
if (lasreader->point.number_of_returns_of_given_pulse < point_min.number_of_returns_of_given_pulse) point_min.number_of_returns_of_given_pulse = lasreader->point.number_of_returns_of_given_pulse;
|
|
else if (lasreader->point.number_of_returns_of_given_pulse > point_max.number_of_returns_of_given_pulse) point_max.number_of_returns_of_given_pulse = lasreader->point.number_of_returns_of_given_pulse;
|
|
if (lasreader->point.return_number < point_min.return_number) point_min.return_number = lasreader->point.return_number;
|
|
else if (lasreader->point.return_number > point_max.return_number) point_max.return_number = lasreader->point.return_number;
|
|
if (lasreader->point.classification < point_min.classification) point_min.classification = lasreader->point.classification;
|
|
else if (lasreader->point.classification > point_max.classification) point_max.classification = lasreader->point.classification;
|
|
if (lasreader->point.scan_angle_rank < point_min.scan_angle_rank) point_min.scan_angle_rank = lasreader->point.scan_angle_rank;
|
|
else if (lasreader->point.scan_angle_rank > point_max.scan_angle_rank) point_max.scan_angle_rank = lasreader->point.scan_angle_rank;
|
|
if (lasreader->point.user_data < point_min.user_data) point_min.user_data = lasreader->point.user_data;
|
|
else if (lasreader->point.user_data > point_max.user_data) point_max.user_data = lasreader->point.user_data;
|
|
if (lasreader->point.point_source_ID < point_min.point_source_ID) point_min.point_source_ID = lasreader->point.point_source_ID;
|
|
else if (lasreader->point.point_source_ID > point_max.point_source_ID) point_max.point_source_ID = lasreader->point.point_source_ID;
|
|
if (lasreader->point.point_source_ID < point_min.point_source_ID) point_min.point_source_ID = lasreader->point.point_source_ID;
|
|
else if (lasreader->point.point_source_ID > point_max.point_source_ID) point_max.point_source_ID = lasreader->point.point_source_ID;
|
|
if (lasreader->points_have_gps_time)
|
|
{
|
|
if (lasreader->gps_time < gps_time_min) gps_time_min = lasreader->gps_time;
|
|
else if (lasreader->gps_time > gps_time_max) gps_time_max = lasreader->gps_time;
|
|
}
|
|
if (lasreader->points_have_rgb)
|
|
{
|
|
if (lasreader->rgb[0] < rgb_min[0]) rgb_min[0] = lasreader->rgb[0];
|
|
else if (lasreader->rgb[0] > rgb_max[0]) rgb_max[0] = lasreader->rgb[0];
|
|
if (lasreader->rgb[1] < rgb_min[1]) rgb_min[1] = lasreader->rgb[1];
|
|
else if (lasreader->rgb[1] > rgb_max[1]) rgb_max[1] = lasreader->rgb[1];
|
|
if (lasreader->rgb[2] < rgb_min[2]) rgb_min[2] = lasreader->rgb[2];
|
|
else if (lasreader->rgb[2] > rgb_max[2]) rgb_max[2] = lasreader->rgb[2];
|
|
}
|
|
}
|
|
fprintf(stderr, "x %d %d %d\n",point_min.x, point_max.x, point_max.x - point_min.x);
|
|
fprintf(stderr, "y %d %d %d\n",point_min.y, point_max.y, point_max.y - point_min.y);
|
|
fprintf(stderr, "z %d %d %d\n",point_min.z, point_max.z, point_max.z - point_min.z);
|
|
fprintf(stderr, "intensity %d %d %d\n",point_min.intensity, point_max.intensity, point_max.intensity - point_min.intensity);
|
|
fprintf(stderr, "edge_of_flight_line %d %d %d\n",point_min.edge_of_flight_line, point_max.edge_of_flight_line, point_max.edge_of_flight_line - point_min.edge_of_flight_line);
|
|
fprintf(stderr, "scan_direction_flag %d %d %d\n",point_min.scan_direction_flag, point_max.scan_direction_flag, point_max.scan_direction_flag - point_min.scan_direction_flag);
|
|
fprintf(stderr, "number_of_returns_of_given_pulse %d %d %d\n",point_min.number_of_returns_of_given_pulse, point_max.number_of_returns_of_given_pulse, point_max.number_of_returns_of_given_pulse - point_min.number_of_returns_of_given_pulse);
|
|
fprintf(stderr, "return_number %d %d %d\n",point_min.return_number, point_max.return_number, point_max.return_number - point_min.return_number);
|
|
fprintf(stderr, "classification %d %d %d\n",point_min.classification, point_max.classification, point_max.classification - point_min.classification);
|
|
fprintf(stderr, "scan_angle_rank %d %d %d\n",point_min.scan_angle_rank, point_max.scan_angle_rank, point_max.scan_angle_rank - point_min.scan_angle_rank);
|
|
fprintf(stderr, "user_data %d %d %d\n",point_min.user_data, point_max.user_data, point_max.user_data - point_min.user_data);
|
|
fprintf(stderr, "point_source_ID %d %d %d\n",point_min.point_source_ID, point_max.point_source_ID, point_max.point_source_ID - point_min.point_source_ID);
|
|
if (lasreader->points_have_gps_time)
|
|
{
|
|
fprintf(stderr, "gps_time %.8f %.8f %.8f\n",gps_time_min, gps_time_max, gps_time_max - gps_time_min);
|
|
}
|
|
if (lasreader->points_have_rgb)
|
|
{
|
|
fprintf(stderr, "R %d %d %d\n",rgb_min[0], rgb_max[0], rgb_max[0] - rgb_min[0]);
|
|
fprintf(stderr, "G %d %d %d\n",rgb_min[1], rgb_max[1], rgb_max[1] - rgb_min[1]);
|
|
fprintf(stderr, "B %d %d %d\n",rgb_min[2], rgb_max[2], rgb_max[2] - rgb_min[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (lasreader->read_point());
|
|
}
|
|
fprintf(stderr,"total reading time: %g seconds\n", taketime()-start_time);*)
|
|
end
|
|
else
|
|
begin
|
|
// create output file name if needed
|
|
|
|
if (file_name_out == 0 && !olas && !olaz)
|
|
{
|
|
int len = strlen(file_name_in);
|
|
file_name_out = strdup(file_name_in);
|
|
if (strstr(file_name_in, ".las"))
|
|
{
|
|
file_name_out[len-4] = '.';
|
|
file_name_out[len-3] = 'l';
|
|
file_name_out[len-2] = 'a';
|
|
file_name_out[len-1] = 'z';
|
|
}
|
|
else if (strstr(file_name_in, ".laz"))
|
|
{
|
|
file_name_out[len-4] = '.';
|
|
file_name_out[len-3] = 'l';
|
|
file_name_out[len-2] = 'a';
|
|
file_name_out[len-1] = 's';
|
|
}
|
|
else if (strstr(file_name_in, ".las.lz"))
|
|
{
|
|
file_name_out[len-7] = '.';
|
|
file_name_out[len-6] = 'l';
|
|
file_name_out[len-5] = 'a';
|
|
file_name_out[len-4] = 's';
|
|
file_name_out[len-3] = '\0';
|
|
}
|
|
else if (strstr(file_name_in, ".LAS"))
|
|
{
|
|
file_name_out[len-4] = '.';
|
|
file_name_out[len-3] = 'L';
|
|
file_name_out[len-2] = 'A';
|
|
file_name_out[len-1] = 'Z';
|
|
}
|
|
else if (strstr(file_name_in, ".LAZ"))
|
|
{
|
|
file_name_out[len-4] = '.';
|
|
file_name_out[len-3] = 'L';
|
|
file_name_out[len-2] = 'A';
|
|
file_name_out[len-1] = 'S';
|
|
}
|
|
else if (strstr(file_name_in, ".LAS.LZ"))
|
|
{
|
|
file_name_out[len-7] = '.';
|
|
file_name_out[len-6] = 'L';
|
|
file_name_out[len-5] = 'A';
|
|
file_name_out[len-4] = 'S';
|
|
file_name_out[len-3] = '\0';
|
|
}
|
|
}
|
|
|
|
// open output file
|
|
|
|
int compression = 0;
|
|
|
|
FILE* file_out = 0;
|
|
if (file_name_out)
|
|
{
|
|
file_out = fopen(file_name_out, "wb");
|
|
if (strstr(file_name_out, ".laz") || strstr(file_name_out, ".las.lz") || strstr(file_name_out, ".LAZ") || strstr(file_name_out, ".LAS.LZ"))
|
|
{
|
|
compression = 1;
|
|
}
|
|
}
|
|
else if (olas || olaz)
|
|
{
|
|
file_out = stdout;
|
|
if (olaz)
|
|
{
|
|
compression = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "ERROR: no output specified\n");
|
|
usage(argc==1);
|
|
}
|
|
|
|
if (verbose) start_time = taketime();
|
|
|
|
LASwriter* laswriter = new LASwriter();
|
|
|
|
if (compression)
|
|
{
|
|
if (range)
|
|
{
|
|
compression = LAS_COMPRESSION_RANGE;
|
|
}
|
|
else
|
|
{
|
|
compression = LAS_COMPRESSION_ARITHMETIC;
|
|
}
|
|
}
|
|
|
|
if (laswriter->open(file_out, &(lasreader->header), compression) == false)
|
|
{
|
|
fprintf(stderr, "ERROR: could not open laswriter\n");
|
|
byebye(argc==1);
|
|
}
|
|
|
|
// loop over points
|
|
|
|
while (lasreader->read_point())
|
|
{
|
|
if (lasreader->p_count == 40)
|
|
{
|
|
lasreader->p_count = 40;
|
|
}
|
|
laswriter->write_point(&(lasreader->point), lasreader->gps_time, lasreader->rgb);
|
|
}
|
|
|
|
int total_bytes = laswriter->close();
|
|
|
|
if (verbose) fprintf(stderr,"total compression: %g sec %d bytes for %d points of format %d\n", taketime()-start_time, total_bytes, lasreader->p_count, lasreader->header.point_data_format);
|
|
|
|
delete laswriter;
|
|
fclose(file_out);
|
|
}
|
|
|
|
lasreader.close();
|
|
lasreader.Free;
|
|
file_in.Free;
|
|
|
|
ExitProgram(argc==1);
|
|
|
|
//return 0;
|
|
end.
|
|
|