netzel commited on 2024-02-21 22:59:38
Showing 5 changed files, with 1462 additions and 0 deletions.
... | ... |
@@ -0,0 +1,40 @@ |
1 |
+ |
|
2 |
+PROG = libezgdal |
|
3 |
+ |
|
4 |
+SWIG = swig -python |
|
5 |
+CC = gcc -Wall -g |
|
6 |
+AR = ar -cvq |
|
7 |
+#CFLAGS = -fdata-sections -ffunction-sections -Wl,--gc-sections |
|
8 |
+CFLAGS = -lgdal -I/usr/include/gdal |
|
9 |
+ |
|
10 |
+COMMON = ezgdal.c |
|
11 |
+COMMON_O = $(COMMON:%.c=%.o) |
|
12 |
+HEADERS = $(shell ls *.h) |
|
13 |
+ |
|
14 |
+ifndef PREFIX |
|
15 |
+ PREFIX = /usr/local |
|
16 |
+endif |
|
17 |
+ |
|
18 |
+ |
|
19 |
+default: $(PROG).so |
|
20 |
+ |
|
21 |
+#$(PROG).a: $(COMMON_O) |
|
22 |
+# $(AR) $(PROG).a $(COMMON_O) |
|
23 |
+ |
|
24 |
+$(PROG).so: $(COMMON_O) |
|
25 |
+ $(CC) $(CFLAGS) -shared -Wl,-soname,$(PROG).so -o $(PROG).so $(COMMON_O) |
|
26 |
+ |
|
27 |
+python: ezgdal.c ezgdal.h ezgdal.i |
|
28 |
+ $(SWIG) ezgdal.i |
|
29 |
+ $(CC) $(CFLAGS) -fPIC -c ezgdal.c ezgdal_wrap.c -I/usr/include/python3.7m |
|
30 |
+ $(CC) $(CFLAGS) -shared ezgdal.o ezgdal_wrap.o -o _ezgdal.so |
|
31 |
+ |
|
32 |
+$(COMMON_O): $(COMMON) $(HEADERS) |
|
33 |
+ $(CC) $(CFLAGS) -fPIC -c $(COMMON) |
|
34 |
+ |
|
35 |
+install: |
|
36 |
+ cp -f $(PROG).so $(PREFIX)/lib |
|
37 |
+ cp -f ezgdal.h $(PREFIX)/include |
|
38 |
+ |
|
39 |
+clean: |
|
40 |
+ rm -f *.o libezgdal.a libezgdal.so *.py *_wrap.c |
|
0 | 41 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,31 @@ |
1 |
+ |
|
2 |
+PROG = libezgdal |
|
3 |
+ |
|
4 |
+CC = x86_64-w64-mingw32-gcc -Wall -O3 |
|
5 |
+LT = x86_64-w64-mingw32-dlltool |
|
6 |
+ |
|
7 |
+CFLAGS = -D_MSC_VER -I ../../Win64_cross/gdal/include -L ../../Win64_cross/gdal/bin -lgdal |
|
8 |
+ |
|
9 |
+COMMON = ezgdal.c |
|
10 |
+COMMON_O = $(COMMON:%.c=%.o) |
|
11 |
+HEADERS = $(shell ls *.h) |
|
12 |
+ |
|
13 |
+default: $(PROG).dll |
|
14 |
+ |
|
15 |
+#$(PROG).a: $(COMMON_O) |
|
16 |
+# $(AR) $(PROG).a $(COMMON_O) |
|
17 |
+ |
|
18 |
+$(PROG).dll: $(COMMON_O) |
|
19 |
+# $(LT) -e exports.o -l $(PROG).lib ezgdal.o |
|
20 |
+ $(CC) $(CFLAGS) -shared -o $(PROG).dll ezgdal.c |
|
21 |
+ |
|
22 |
+#$(COMMON_O): $(COMMON) $(HEADERS) |
|
23 |
+# $(CC) $(CFLAGS) -c $(COMMON) |
|
24 |
+ |
|
25 |
+install: |
|
26 |
+ cp ezgdal.h ../../Win64_cross/ezgdal |
|
27 |
+ mv $(PROG).dll ../../Win64_cross/ezgdal |
|
28 |
+ mv $(PROG).lib ../../Win64_cross/ezgdal |
|
29 |
+ |
|
30 |
+clean: |
|
31 |
+ rm -f *.o $(PROG).dll *.lib |
|
0 | 32 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,1030 @@ |
1 |
+/**************************************************************************** |
|
2 |
+ * |
|
3 |
+ * LIBRARY: ezGDAL - easy GDAL access |
|
4 |
+ * AUTHOR(S): Pawel Netzel |
|
5 |
+ * PURPOSE: library for reading GDAL layers, writting GeoTIFFs, processing |
|
6 |
+ * data row-by-row, stripe-by-stripe, frame-by-frame |
|
7 |
+ * COPYRIGHT: (C) Pawel Netzel |
|
8 |
+ * http://pawel.netzel.pl |
|
9 |
+ * |
|
10 |
+ * This program is free software under the GNU Lesser General |
|
11 |
+ * Public License (>=v3). Read the file lgpl-3.0.txt |
|
12 |
+ * |
|
13 |
+ *****************************************************************************/ |
|
14 |
+ |
|
15 |
+ |
|
16 |
+ |
|
17 |
+#include <stdlib.h> |
|
18 |
+#include <stdio.h> |
|
19 |
+#include <float.h> |
|
20 |
+#include <limits.h> |
|
21 |
+#include <assert.h> |
|
22 |
+#include <gdal.h> |
|
23 |
+#include <ogr_srs_api.h> |
|
24 |
+#include <cpl_string.h> |
|
25 |
+ |
|
26 |
+ |
|
27 |
+#define DLL_EXPORT |
|
28 |
+ |
|
29 |
+#include "ezgdal.h" |
|
30 |
+ |
|
31 |
+ |
|
32 |
+/*==========================================*/ |
|
33 |
+/* UTILS */ |
|
34 |
+/* */ |
|
35 |
+ |
|
36 |
+static unsigned long max_frame_buffer_size = MAX_FRAME_BUFFER_SIZE; |
|
37 |
+ |
|
38 |
+int ezgdal_file_exists(const char *fname) { |
|
39 |
+ FILE *f = fopen(fname,"r"); |
|
40 |
+ if(f) { |
|
41 |
+ fclose(f); |
|
42 |
+ return 1; |
|
43 |
+ } |
|
44 |
+ return 0; |
|
45 |
+} |
|
46 |
+ |
|
47 |
+void ezgdal_show_progress(FILE *f, int i, int N) { |
|
48 |
+ static int percent = -1; |
|
49 |
+ int n; |
|
50 |
+ if(N==0 || i<0 || i>N) |
|
51 |
+ n = 0; |
|
52 |
+ else |
|
53 |
+ n = (int)(100.0*(double)i/(double)N); |
|
54 |
+ if(percent!=n) { |
|
55 |
+ percent=n; |
|
56 |
+ fprintf(f, "\b\b\b\b%3d%%",percent); |
|
57 |
+ fflush(f); |
|
58 |
+ if(percent==100) |
|
59 |
+ fprintf(f, "\n"); |
|
60 |
+ } |
|
61 |
+} |
|
62 |
+ |
|
63 |
+void ezgdal_show_message(FILE *f, char *message) { |
|
64 |
+ fprintf(f,"%s\n",message); |
|
65 |
+ fflush(f); |
|
66 |
+} |
|
67 |
+ |
|
68 |
+void ezgdal_show_message_nolf(FILE *f, char *message) { |
|
69 |
+ fprintf(f,"%s",message); |
|
70 |
+ fflush(f); |
|
71 |
+} |
|
72 |
+ |
|
73 |
+double ezgdal_get_value(double *array, int idx) { |
|
74 |
+ return array[idx]; |
|
75 |
+} |
|
76 |
+ |
|
77 |
+void ezgdal_set_value(double *array, int idx, double val) { |
|
78 |
+ array[idx]=val; |
|
79 |
+} |
|
80 |
+ |
|
81 |
+ |
|
82 |
+/*==========================================*/ |
|
83 |
+/* TOOLS */ |
|
84 |
+/* */ |
|
85 |
+ |
|
86 |
+int ezgdal_is_bbox_ok(EZGDAL_LAYER **inputs, int ninputs) { |
|
87 |
+ double eps = 0.00000000001; |
|
88 |
+ double geo_transform[2][6]; |
|
89 |
+ int i,j; |
|
90 |
+ |
|
91 |
+ if(ninputs<2) return 1; |
|
92 |
+ GDALGetGeoTransform(inputs[0]->dataset_h,geo_transform[0]); |
|
93 |
+ for(i=1; i<ninputs; i++) { |
|
94 |
+ GDALGetGeoTransform(inputs[i]->dataset_h,geo_transform[1]); |
|
95 |
+ for(j=0; j<6; j++) |
|
96 |
+ if(fabs(geo_transform[0][j]-geo_transform[1][j])>eps) |
|
97 |
+ return 0; |
|
98 |
+ } |
|
99 |
+ return 1; |
|
100 |
+} |
|
101 |
+ |
|
102 |
+int ezgdal_is_projection_ok(EZGDAL_LAYER **inputs, int ninputs) { |
|
103 |
+ int i = 1; |
|
104 |
+ int proj_ok = TRUE; |
|
105 |
+ char *p, *p1; |
|
106 |
+ OGRSpatialReferenceH ref, ref1; |
|
107 |
+ |
|
108 |
+ if(ninputs<2) |
|
109 |
+ return TRUE; |
|
110 |
+ |
|
111 |
+ p = (char *)GDALGetProjectionRef(inputs[0]->dataset_h); |
|
112 |
+ |
|
113 |
+ ref = OSRNewSpatialReference(p); |
|
114 |
+ |
|
115 |
+ while(proj_ok && i<ninputs) { |
|
116 |
+ p1 = (char *)GDALGetProjectionRef(inputs[i]->dataset_h); |
|
117 |
+ ref1 = OSRNewSpatialReference(p1); |
|
118 |
+ proj_ok = proj_ok && ((p==NULL && p1==NULL) || (p!=NULL && p1!=NULL && OSRIsSame(ref,ref1))); |
|
119 |
+ |
|
120 |
+ OSRDestroySpatialReference(ref1); |
|
121 |
+ i++; |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ OSRDestroySpatialReference(ref); |
|
125 |
+ return proj_ok; |
|
126 |
+} |
|
127 |
+ |
|
128 |
+GDALDataType ezgdal_data_type(char *data) { |
|
129 |
+ if(data==NULL) |
|
130 |
+ return GDT_Float64; |
|
131 |
+ if(strcmp(data,"Byte")==0) |
|
132 |
+ return GDT_Byte; |
|
133 |
+ else if(strcmp(data,"UInt16")==0) |
|
134 |
+ return GDT_UInt16; |
|
135 |
+ else if(strcmp(data,"Int16")==0) |
|
136 |
+ return GDT_Int16; |
|
137 |
+ else if(strcmp(data,"UInt32")==0) |
|
138 |
+ return GDT_UInt32; |
|
139 |
+ else if(strcmp(data,"Int32")==0) |
|
140 |
+ return GDT_Int32; |
|
141 |
+ else if(strcmp(data,"Float32")==0) |
|
142 |
+ return GDT_Float32; |
|
143 |
+ else if(strcmp(data,"Float64")==0) |
|
144 |
+ return GDT_Float64; |
|
145 |
+ else |
|
146 |
+ return GDT_Float64; |
|
147 |
+} |
|
148 |
+ |
|
149 |
+char* ezgdal_layer_get_wkt(EZGDAL_LAYER *layer) { |
|
150 |
+ char *p = (char *)GDALGetProjectionRef(layer->dataset_h); |
|
151 |
+ return p; |
|
152 |
+} |
|
153 |
+ |
|
154 |
+double* ezgdal_layer_get_at(EZGDAL_LAYER *layer) { |
|
155 |
+ double *p = malloc(6*sizeof(double)); |
|
156 |
+ |
|
157 |
+ GDALGetGeoTransform(layer->dataset_h, p); |
|
158 |
+ return p; |
|
159 |
+} |
|
160 |
+ |
|
161 |
+int ezgdal_xy2c(EZGDAL_LAYER *layer, double x, double y) { |
|
162 |
+ double *a = ezgdal_layer_get_at(layer); |
|
163 |
+ return (int)floor((x - a[0])/a[1]); |
|
164 |
+ |
|
165 |
+ |
|
166 |
+/* |
|
167 |
+ double c0 = a[2]*a[4]-a[1]*a[5]; |
|
168 |
+ if(a[2]!=0.0 && c0!=0.0) |
|
169 |
+ return (int)((a[0]*a[5]-a[2]*a[3]+a[2]*y-a[5]*x)/c0); |
|
170 |
+ else if(a[2]==0 && a[1]!=0.0 && a[5]!=0.0) |
|
171 |
+ return (int)((x-a[0])/a[1]); |
|
172 |
+ else |
|
173 |
+ return -1; |
|
174 |
+*/ |
|
175 |
+}; |
|
176 |
+double ezgdal_cr2x(EZGDAL_LAYER *layer, int col, int row) { |
|
177 |
+ double *a = ezgdal_layer_get_at(layer); |
|
178 |
+ return a[0]+a[1]*col+a[2]*row; |
|
179 |
+}; |
|
180 |
+ |
|
181 |
+int ezgdal_xy2r(EZGDAL_LAYER *layer, double x, double y) { |
|
182 |
+ double *a = ezgdal_layer_get_at(layer); |
|
183 |
+ return (int)floor((y - a[3])/a[5]); |
|
184 |
+ |
|
185 |
+/* |
|
186 |
+ double c0 = a[2]*a[4]-a[1]*a[5]; |
|
187 |
+ if(a[2]!=0.0 && c0!=0) |
|
188 |
+ return (int)((-a[0]*a[4]+a[1]*a[3]-a[1]*y+a[4]*x)/c0); |
|
189 |
+ else if(a[2]==0.0 && a[1]!=0.0 && a[5]!=0.0) |
|
190 |
+ return (int)((a[0]*a[4]-a[1]*a[3]+a[1]*y-a[4]*x)/(a[1]*a[5])); |
|
191 |
+ else |
|
192 |
+ return -1; |
|
193 |
+*/ |
|
194 |
+}; |
|
195 |
+double ezgdal_cr2y(EZGDAL_LAYER *layer, int col, int row) { |
|
196 |
+ double *a = ezgdal_layer_get_at(layer); |
|
197 |
+ return a[3]+a[4]*col+a[5]*row; |
|
198 |
+}; |
|
199 |
+ |
|
200 |
+ |
|
201 |
+ |
|
202 |
+ |
|
203 |
+/*==========================================*/ |
|
204 |
+/* LAYER */ |
|
205 |
+/* */ |
|
206 |
+ |
|
207 |
+EZGDAL_LAYER* ezgdal_open_layer_mode(char *fname, GDALAccess mode, int band) { |
|
208 |
+ |
|
209 |
+ EZGDAL_LAYER *layer = NULL; |
|
210 |
+ |
|
211 |
+ if(!ezgdal_file_exists(fname)) { |
|
212 |
+ ezgdal_show_message(stderr,"Input file does not exist!"); |
|
213 |
+ return NULL; |
|
214 |
+ } |
|
215 |
+ |
|
216 |
+ GDALAllRegister(); |
|
217 |
+ |
|
218 |
+ layer = (EZGDAL_LAYER *)calloc(1,sizeof(EZGDAL_LAYER)); |
|
219 |
+ |
|
220 |
+ layer->dataset_h = GDALOpen(fname,mode); |
|
221 |
+ if(!(layer->dataset_h)) { |
|
222 |
+ ezgdal_show_message(stderr,"Problem with open input file!!"); |
|
223 |
+ return NULL; |
|
224 |
+ } |
|
225 |
+ |
|
226 |
+ layer->band_h = GDALGetRasterBand(layer->dataset_h, band); |
|
227 |
+ if(!(layer->band_h)) { |
|
228 |
+ ezgdal_show_message(stderr,"Problem with open selected band!!"); |
|
229 |
+ return NULL; |
|
230 |
+ } |
|
231 |
+ |
|
232 |
+ layer->cols = GDALGetRasterBandXSize(layer->band_h); |
|
233 |
+ layer->rows = GDALGetRasterBandYSize(layer->band_h); |
|
234 |
+ |
|
235 |
+ layer->no_data = GDALGetRasterNoDataValue(layer->band_h, &(layer->is_no_data)); |
|
236 |
+ layer->buffer = (double *)malloc(layer->cols*sizeof(double)); |
|
237 |
+ layer->stripe = NULL; |
|
238 |
+ layer->frameset = NULL; |
|
239 |
+ |
|
240 |
+ return layer; |
|
241 |
+} |
|
242 |
+ |
|
243 |
+EZGDAL_LAYER* ezgdal_open_layer(char *fname) { |
|
244 |
+ |
|
245 |
+ return ezgdal_open_layer_mode(fname, GA_ReadOnly, 1); |
|
246 |
+ |
|
247 |
+} |
|
248 |
+ |
|
249 |
+EZGDAL_LAYER* ezgdal_open_layer_band(char *fname, int band) { |
|
250 |
+ |
|
251 |
+ return ezgdal_open_layer_mode(fname, GA_ReadOnly, band); |
|
252 |
+ |
|
253 |
+} |
|
254 |
+ |
|
255 |
+EZGDAL_LAYER* ezgdal_open_layer_rw(char *fname) { |
|
256 |
+ |
|
257 |
+ return ezgdal_open_layer_mode(fname, GA_Update, 1); |
|
258 |
+ |
|
259 |
+} |
|
260 |
+ |
|
261 |
+void ezgdal_set_palette255(EZGDAL_LAYER *layer, double palette[][5], int n) { |
|
262 |
+ |
|
263 |
+ GDALColorTableH ct = GDALCreateColorTable(GPI_RGB); |
|
264 |
+ int i,i1,i2; |
|
265 |
+ GDALColorEntry c1,c2; |
|
266 |
+ |
|
267 |
+ for(i=0; i<n-1; i++) { |
|
268 |
+ c1.c1 = (short)palette[i][1]; |
|
269 |
+ c1.c2 = (short)palette[i][2]; |
|
270 |
+ c1.c3 = (short)palette[i][3]; |
|
271 |
+ c1.c4 = (short)palette[i][4]; |
|
272 |
+ i1 = (int)palette[i][0]; |
|
273 |
+ c2.c1 = (short)palette[i+1][1]; |
|
274 |
+ c2.c2 = (short)palette[i+1][2]; |
|
275 |
+ c2.c3 = (short)palette[i+1][3]; |
|
276 |
+ c2.c4 = (short)palette[i+1][4]; |
|
277 |
+ i2 = (int)palette[i+1][0]; |
|
278 |
+ GDALCreateColorRamp(ct,i1,&c1,i2,&c2); |
|
279 |
+ } |
|
280 |
+ if(palette[n-1][0]<255) { |
|
281 |
+ c1.c1 = 0; |
|
282 |
+ c1.c2 = 0; |
|
283 |
+ c1.c3 = 0; |
|
284 |
+ c1.c4 = 0; |
|
285 |
+ for(i=(int)palette[n-1][0]+1; i<=255; i++) |
|
286 |
+ GDALSetColorEntry(ct,i,&c1); |
|
287 |
+ } |
|
288 |
+ |
|
289 |
+ GDALSetRasterColorTable(layer->band_h,ct); |
|
290 |
+} |
|
291 |
+ |
|
292 |
+ |
|
293 |
+void free_layer_stats(EZGDAL_LAYER *layer); |
|
294 |
+void ezgdal_free_stripe(EZGDAL_LAYER *layer); |
|
295 |
+ |
|
296 |
+ |
|
297 |
+void ezgdal_close_layer(EZGDAL_LAYER *layer) { |
|
298 |
+ GDALClose(layer->dataset_h); |
|
299 |
+ free(layer->buffer); |
|
300 |
+ free_layer_stats(layer); |
|
301 |
+ ezgdal_free_stripe(layer); |
|
302 |
+ free(layer); |
|
303 |
+} |
|
304 |
+ |
|
305 |
+const char *opts_compress_none[] = { "BIGTIFF=YES", NULL}; |
|
306 |
+const char *opts_compress_deflate2[] = { "BIGTIFF=YES", "COMPRESS=DEFLATE", "PREDICTOR=2", NULL}; |
|
307 |
+const char *opts_compress_lzw[] = { "BIGTIFF=YES", "COMPRESS=LZW", NULL }; |
|
308 |
+ |
|
309 |
+EZGDAL_LAYER* ezgdal_create_layer(char *fname, |
|
310 |
+ char *wkt, |
|
311 |
+ char *d_type, |
|
312 |
+ double *geo_tr, |
|
313 |
+ int rows, |
|
314 |
+ int cols, |
|
315 |
+ int *nodata, |
|
316 |
+ int compress) { |
|
317 |
+ |
|
318 |
+ EZGDAL_LAYER *o; |
|
319 |
+ int is_no_data = FALSE; |
|
320 |
+ double no_data = DBL_MIN; |
|
321 |
+ const char *data_format = "GTiff"; |
|
322 |
+ char **opts = NULL; |
|
323 |
+ GDALDataType data_type; |
|
324 |
+ GDALDriverH driver; |
|
325 |
+ |
|
326 |
+ o = (EZGDAL_LAYER *)calloc(1,sizeof(EZGDAL_LAYER)); |
|
327 |
+ |
|
328 |
+ GDALAllRegister(); |
|
329 |
+ |
|
330 |
+ driver = GDALGetDriverByName(data_format); |
|
331 |
+ if(driver==NULL) { |
|
332 |
+ ezgdal_show_message(stderr,"GDAL: Problem with GeoTiff driver!!"); |
|
333 |
+ exit(1); |
|
334 |
+ } |
|
335 |
+ |
|
336 |
+ data_type = ezgdal_data_type(d_type); |
|
337 |
+ |
|
338 |
+ if(nodata) { |
|
339 |
+ no_data = *nodata; |
|
340 |
+ is_no_data = TRUE; |
|
341 |
+ } |
|
342 |
+ |
|
343 |
+ if(compress==EZGDAL_COMPRESS_DEFLATE) |
|
344 |
+ opts = (char **)opts_compress_deflate2; |
|
345 |
+ else if (compress==EZGDAL_COMPRESS_LZW) |
|
346 |
+ opts = (char **)opts_compress_lzw; |
|
347 |
+ else |
|
348 |
+ opts = (char **)opts_compress_none; |
|
349 |
+ |
|
350 |
+ o->cols = cols; |
|
351 |
+ o->rows = rows; |
|
352 |
+ |
|
353 |
+ o->dataset_h = GDALCreate(driver,fname,o->cols,o->rows,1,data_type,opts); |
|
354 |
+ |
|
355 |
+ if(!(o->dataset_h)) { |
|
356 |
+ ezgdal_show_message(stderr,"Problem with creating file!!"); |
|
357 |
+ exit(1); |
|
358 |
+ } |
|
359 |
+ |
|
360 |
+ o->band_h = GDALGetRasterBand(o->dataset_h,1); |
|
361 |
+ |
|
362 |
+ o->no_data = no_data; |
|
363 |
+ o->is_no_data = is_no_data; |
|
364 |
+ |
|
365 |
+ if(is_no_data) |
|
366 |
+ GDALSetRasterNoDataValue(o->band_h,no_data); |
|
367 |
+ |
|
368 |
+ o->buffer = (double *)malloc(o->cols*sizeof(double)); |
|
369 |
+ o->stripe = NULL; |
|
370 |
+ o->frameset = NULL; |
|
371 |
+ |
|
372 |
+ GDALSetProjection(o->dataset_h,wkt); |
|
373 |
+ GDALSetGeoTransform(o->dataset_h,geo_tr); |
|
374 |
+ |
|
375 |
+ return o; |
|
376 |
+} |
|
377 |
+ |
|
378 |
+void ezgdal_read_buffer(EZGDAL_LAYER *layer, int row) { |
|
379 |
+ int i; |
|
380 |
+ double d = 0.0; |
|
381 |
+ double *p; |
|
382 |
+ if(row<0 || row>=layer->rows) { |
|
383 |
+ if(layer->is_no_data) d = layer->no_data; |
|
384 |
+ p = layer->buffer; |
|
385 |
+ for(i=0; i<layer->cols; i++) |
|
386 |
+ *(p++) = d; |
|
387 |
+ } else |
|
388 |
+ i=GDALRasterIO(layer->band_h, GF_Read,0, row, layer->cols, 1, |
|
389 |
+ layer->buffer, layer->cols, 1, GDT_Float64, 0, 0); |
|
390 |
+} |
|
391 |
+ |
|
392 |
+void ezgdal_write_buffer(EZGDAL_LAYER *layer, int row) { |
|
393 |
+ if(row<0 || row>=layer->rows) return; |
|
394 |
+ CPLErr res = GDALRasterIO(layer->band_h, GF_Write, 0, row, layer->cols, 1, |
|
395 |
+ layer->buffer, layer->cols, 1, GDT_Float64, 0, 0); |
|
396 |
+ if(res>CE_Warning) { |
|
397 |
+ ezgdal_show_message(stderr,"GDAL I/O operation faild!"); |
|
398 |
+ exit(EXIT_FAILURE); |
|
399 |
+ } |
|
400 |
+} |
|
401 |
+ |
|
402 |
+void ezgdal_read_all_layer(EZGDAL_LAYER *layer, double* buffer) { |
|
403 |
+ CPLErr res = GDALRasterIO(layer->band_h, GF_Read, 0, 0, layer->cols, layer->rows, |
|
404 |
+ buffer, layer->cols, layer->rows, GDT_Float64, 0, 0); |
|
405 |
+ if(res>CE_Warning) { |
|
406 |
+ ezgdal_show_message(stderr,"GDAL I/O operation faild!"); |
|
407 |
+ exit(EXIT_FAILURE); |
|
408 |
+ } |
|
409 |
+} |
|
410 |
+ |
|
411 |
+void ezgdal_write_all_layer(EZGDAL_LAYER *layer, double* buffer) { |
|
412 |
+ CPLErr res = GDALRasterIO(layer->band_h, GF_Write, 0, 0, layer->cols, layer->rows, |
|
413 |
+ buffer, layer->cols, layer->rows, GDT_Float64, 0, 0); |
|
414 |
+ if(res>CE_Warning) { |
|
415 |
+ ezgdal_show_message(stderr,"GDAL I/O operation faild!"); |
|
416 |
+ exit(EXIT_FAILURE); |
|
417 |
+ } |
|
418 |
+} |
|
419 |
+ |
|
420 |
+int ezgdal_is_null(EZGDAL_LAYER *layer, double v) { |
|
421 |
+ if((layer->is_no_data) && (v == layer->no_data)) |
|
422 |
+ return TRUE; |
|
423 |
+ return FALSE; |
|
424 |
+} |
|
425 |
+ |
|
426 |
+void ezgdal_set_null(EZGDAL_LAYER *layer, double *v) { |
|
427 |
+ if(layer->is_no_data) |
|
428 |
+ *v = layer->no_data; |
|
429 |
+} |
|
430 |
+ |
|
431 |
+ |
|
432 |
+ |
|
433 |
+/*==========================================*/ |
|
434 |
+/* STATS */ |
|
435 |
+/* */ |
|
436 |
+ |
|
437 |
+void ezgdal_calc_layer_stats(EZGDAL_LAYER *layer) { |
|
438 |
+ |
|
439 |
+ if(layer == NULL) return; |
|
440 |
+ |
|
441 |
+ if(layer->stats == NULL) { |
|
442 |
+ layer->stats = (EZGDAL_STATS *)malloc(sizeof(EZGDAL_STATS)); |
|
443 |
+ |
|
444 |
+ assert(layer->stats!=NULL); |
|
445 |
+ |
|
446 |
+ layer->stats->map_cat = NULL; |
|
447 |
+ layer->stats->hist_N = 0; |
|
448 |
+ layer->stats->map_max_val = 0; |
|
449 |
+ layer->stats->hist_min = 0; |
|
450 |
+ layer->stats->hist_max = 0; |
|
451 |
+ layer->stats->hist_step = 0; |
|
452 |
+ } |
|
453 |
+ |
|
454 |
+ GDALComputeRasterStatistics(layer->band_h, FALSE, |
|
455 |
+ &(layer->stats->min), |
|
456 |
+ &(layer->stats->max), |
|
457 |
+ &(layer->stats->avg), |
|
458 |
+ &(layer->stats->std), |
|
459 |
+ NULL,NULL); |
|
460 |
+} |
|
461 |
+ |
|
462 |
+void ezgdal_calc_value_map(EZGDAL_LAYER *layer, double min, double max, int N) { |
|
463 |
+ |
|
464 |
+#ifdef OLD_GDAL |
|
465 |
+ int *hist; |
|
466 |
+#else |
|
467 |
+ GUIntBig *hist; |
|
468 |
+#endif |
|
469 |
+ |
|
470 |
+ int i,j = 0; |
|
471 |
+ CPLErr res; |
|
472 |
+ |
|
473 |
+ if(layer == NULL) return; |
|
474 |
+ if(min>=max || N<=0) return; |
|
475 |
+ |
|
476 |
+ if(layer->stats == NULL) { |
|
477 |
+ layer->stats = (EZGDAL_STATS *)malloc(sizeof(EZGDAL_STATS)); |
|
478 |
+ |
|
479 |
+ assert(layer->stats!=NULL); |
|
480 |
+ |
|
481 |
+ layer->stats->min = 0; |
|
482 |
+ layer->stats->max = 0; |
|
483 |
+ layer->stats->avg = 0; |
|
484 |
+ layer->stats->std = 0; |
|
485 |
+ } |
|
486 |
+ |
|
487 |
+ layer->stats->hist_min = min; |
|
488 |
+ layer->stats->hist_max = max; |
|
489 |
+ layer->stats->hist_step = (double)N/(max-min); |
|
490 |
+ layer->stats->hist_N = N; |
|
491 |
+ |
|
492 |
+#ifdef OLD_GDAL |
|
493 |
+ hist = (int *) malloc(N * sizeof(int)); |
|
494 |
+#else |
|
495 |
+ hist = (GUIntBig *) malloc(N * sizeof(GUIntBig)); |
|
496 |
+#endif |
|
497 |
+ |
|
498 |
+#ifdef OLD_GDAL |
|
499 |
+ res = GDALGetRasterHistogram(layer->band_h, |
|
500 |
+ min, |
|
501 |
+ max, |
|
502 |
+ N, |
|
503 |
+ hist, |
|
504 |
+ FALSE, FALSE, |
|
505 |
+ NULL, NULL); |
|
506 |
+#else |
|
507 |
+ res = GDALGetRasterHistogramEx(layer->band_h, |
|
508 |
+ min, |
|
509 |
+ max, |
|
510 |
+ N, |
|
511 |
+ hist, |
|
512 |
+ FALSE, FALSE, |
|
513 |
+ NULL, NULL); |
|
514 |
+#endif |
|
515 |
+ |
|
516 |
+ assert(res==CE_None || res==CE_Debug); |
|
517 |
+ |
|
518 |
+ layer->stats->map_cat = (int *)malloc(N * sizeof(int)); |
|
519 |
+ |
|
520 |
+ for(i=0; i<N; i++) |
|
521 |
+ if(hist[i]>0) |
|
522 |
+ layer->stats->map_cat[i] = j++; |
|
523 |
+ else |
|
524 |
+ layer->stats->map_cat[i] = -1; |
|
525 |
+ |
|
526 |
+ layer->stats->map_max_val = j-1; |
|
527 |
+ |
|
528 |
+ free(hist); |
|
529 |
+} |
|
530 |
+ |
|
531 |
+int ezgdal_get_value_index(EZGDAL_LAYER *layer, double val) { |
|
532 |
+ |
|
533 |
+ if(val < layer->stats->hist_min || val > layer->stats->hist_max) |
|
534 |
+ return -1; |
|
535 |
+ |
|
536 |
+ int i = layer->stats->map_cat[(int)( (val - layer->stats->hist_min) * layer->stats->hist_step )]; |
|
537 |
+// if(i==layer->stats->map_max_val) i--; |
|
538 |
+ return i; |
|
539 |
+} |
|
540 |
+ |
|
541 |
+double ezgdal_get_index_value(EZGDAL_LAYER *layer, int idx) { |
|
542 |
+ |
|
543 |
+ if(idx < 0 || idx >= layer->stats->hist_N) |
|
544 |
+ return -1; |
|
545 |
+ |
|
546 |
+ int i; |
|
547 |
+ for(i=0; i<layer->stats->hist_N; i++) |
|
548 |
+ if(layer->stats->map_cat[i]==idx) |
|
549 |
+ return (i + 0.5) / layer->stats->hist_step + layer->stats->hist_min; |
|
550 |
+ |
|
551 |
+ return -1; |
|
552 |
+} |
|
553 |
+ |
|
554 |
+void free_layer_stats(EZGDAL_LAYER *layer) { |
|
555 |
+ |
|
556 |
+ if(layer == NULL) return; |
|
557 |
+ |
|
558 |
+ if(layer->stats != NULL) { |
|
559 |
+ if(layer->stats->map_cat != NULL) |
|
560 |
+ free(layer->stats->map_cat); |
|
561 |
+ free(layer->stats); |
|
562 |
+ } |
|
563 |
+} |
|
564 |
+ |
|
565 |
+ |
|
566 |
+ |
|
567 |
+/*==========================================*/ |
|
568 |
+/* STRIPE & FRAME */ |
|
569 |
+/* */ |
|
570 |
+ |
|
571 |
+EZGDAL_STRIPE* ezgdal_create_stripe(EZGDAL_LAYER *layer, int row1, int height) { |
|
572 |
+ int r, c; |
|
573 |
+ EZGDAL_STRIPE *s; |
|
574 |
+ double d = 0.0, *p; |
|
575 |
+ |
|
576 |
+ if(layer==NULL) return NULL; |
|
577 |
+ |
|
578 |
+ if(row1<-height || row1>layer->rows-height-1) return NULL; |
|
579 |
+ |
|
580 |
+ if(layer->is_no_data) d = layer->no_data; |
|
581 |
+ s = malloc(sizeof(EZGDAL_STRIPE)); |
|
582 |
+ s->layer = layer; |
|
583 |
+ s->rows = height; |
|
584 |
+ s->row1 = INT_MIN; |
|
585 |
+ s->row2 = s->row1 + height - 1; |
|
586 |
+ s->buffer = malloc((s->rows) * sizeof(double *)); |
|
587 |
+ for(r=0; r<s->rows; r++) { |
|
588 |
+ s->buffer[r] = malloc((layer->cols + 2*height) * sizeof(double)); |
|
589 |
+ p = s->buffer[r]; |
|
590 |
+ for(c=0; c<layer->cols+2*height; c++) |
|
591 |
+ *(p++) = d; |
|
592 |
+ } |
|
593 |
+ s->frame = NULL; |
|
594 |
+ s->frames = 0; |
|
595 |
+ |
|
596 |
+ layer->stripe = s; |
|
597 |
+ |
|
598 |
+ return s; |
|
599 |
+} |
|
600 |
+ |
|
601 |
+void reset_frame_buffer_pointers(EZGDAL_STRIPE *stripe) { |
|
602 |
+ int f,r; |
|
603 |
+ |
|
604 |
+ if(stripe->frame==NULL) return; |
|
605 |
+ |
|
606 |
+ for(f=0; f<stripe->frames; f++) { |
|
607 |
+ stripe->frame[f].row1 = stripe->row1; |
|
608 |
+ stripe->frame[f].row2 = stripe->row2; |
|
609 |
+ for(r=0; r<stripe->rows; r++) |
|
610 |
+ stripe->frame[f].buffer[r] = stripe->buffer[r] + stripe->frame[f].col1 + stripe->rows; |
|
611 |
+ } |
|
612 |
+} |
|
613 |
+ |
|
614 |
+EZGDAL_FRAME* ezgdal_create_frame(EZGDAL_STRIPE *stripe, int col1) { |
|
615 |
+ EZGDAL_FRAME *f; |
|
616 |
+ |
|
617 |
+ if(stripe == NULL) return NULL; |
|
618 |
+ if(stripe->frame!=NULL) return NULL; |
|
619 |
+ if(col1<-stripe->rows || col1>stripe->layer->cols-stripe->rows-1) return NULL; |
|
620 |
+ |
|
621 |
+ f = calloc(1,sizeof(EZGDAL_FRAME)); |
|
622 |
+ f->owner.stripe = stripe; |
|
623 |
+ f->cols = stripe->rows; |
|
624 |
+ f->rows = stripe->rows; |
|
625 |
+ f->row1 = stripe->row1; |
|
626 |
+ f->row2 = stripe->row2; |
|
627 |
+ f->col1 = col1; |
|
628 |
+ f->col2 = f->col1 + f->cols - 1; |
|
629 |
+ f->buffer = malloc(stripe->rows * sizeof(double *)); |
|
630 |
+ stripe->frame = f; |
|
631 |
+ stripe->frames = 1; |
|
632 |
+ reset_frame_buffer_pointers(stripe); |
|
633 |
+ return f; |
|
634 |
+} |
|
635 |
+ |
|
636 |
+int ezgdal_create_all_frames(EZGDAL_STRIPE *stripe, int start, int shift) { |
|
637 |
+ int r, s, N; |
|
638 |
+ |
|
639 |
+ if(stripe == NULL) return 0; |
|
640 |
+ if(stripe->frame!=NULL) return 0; |
|
641 |
+ |
|
642 |
+ if(start<-stripe->rows || start>stripe->layer->cols-stripe->rows-1) return 0; |
|
643 |
+ N = 0; |
|
644 |
+ s = start; |
|
645 |
+ while(s>-stripe->rows && s<stripe->layer->cols) { |
|
646 |
+ N++; |
|
647 |
+ s += shift; |
|
648 |
+ } |
|
649 |
+ if(N==0) return 0; |
|
650 |
+ stripe->frame = calloc(N, sizeof(EZGDAL_FRAME)); |
|
651 |
+ stripe->frames = N; |
|
652 |
+ for(r=0; r<N; r++) { |
|
653 |
+ stripe->frame[r].owner.stripe = stripe; |
|
654 |
+ stripe->frame[r].cols = stripe->rows; |
|
655 |
+ stripe->frame[r].rows = stripe->rows; |
|
656 |
+ stripe->frame[r].row1 = stripe->row1; |
|
657 |
+ stripe->frame[r].row2 = stripe->row2; |
|
658 |
+ stripe->frame[r].col1 = start; |
|
659 |
+ stripe->frame[r].col2 = stripe->frame[r].col1 + stripe->rows - 1; |
|
660 |
+ stripe->frame[r].buffer = malloc(stripe->rows * sizeof(double *)); |
|
661 |
+ start += shift; |
|
662 |
+ } |
|
663 |
+ reset_frame_buffer_pointers(stripe); |
|
664 |
+ return N; |
|
665 |
+} |
|
666 |
+ |
|
667 |
+void ezgdal_shift_frame_pos(EZGDAL_FRAME *frame, int col) { |
|
668 |
+ |
|
669 |
+ if(frame==NULL || frame->owner.stripe->frames!=1) return; |
|
670 |
+// if(col<frame->cols || col>frame->owner.stripe->layer->cols-frame->cols-1) return; |
|
671 |
+ if(col<-frame->cols || col>frame->owner.stripe->layer->cols-1) return; |
|
672 |
+ |
|
673 |
+ frame->col1 = col; |
|
674 |
+ frame->col2 = frame->col1 + frame->cols - 1; |
|
675 |
+ reset_frame_buffer_pointers(frame->owner.stripe); |
|
676 |
+} |
|
677 |
+ |
|
678 |
+void ezgdal_free_all_frames(EZGDAL_STRIPE *stripe) { |
|
679 |
+ int f; |
|
680 |
+ if(stripe->frame!=NULL) { |
|
681 |
+ for(f=0; f<stripe->frames; f++) |
|
682 |
+ free(stripe->frame[f].buffer); |
|
683 |
+ free(stripe->frame); |
|
684 |
+ stripe->frame = NULL; |
|
685 |
+ stripe->frames = 0; |
|
686 |
+ } |
|
687 |
+} |
|
688 |
+ |
|
689 |
+void ezgdal_free_stripe(EZGDAL_LAYER *layer) { |
|
690 |
+ int r; |
|
691 |
+ if(layer->stripe==NULL) return; |
|
692 |
+ ezgdal_free_all_frames(layer->stripe); |
|
693 |
+ for(r=0; r<layer->stripe->rows; r++) |
|
694 |
+ free(layer->stripe->buffer[r]); |
|
695 |
+ free(layer->stripe->buffer); |
|
696 |
+ free(layer->stripe); |
|
697 |
+ layer->stripe = NULL; |
|
698 |
+} |
|
699 |
+ |
|
700 |
+EZGDAL_FRAME* ezgdal_get_frame(EZGDAL_STRIPE *stripe, int idx) { |
|
701 |
+ if(idx<0 || idx>=stripe->frames) return NULL; |
|
702 |
+ return &(stripe->frame[idx]); |
|
703 |
+} |
|
704 |
+ |
|
705 |
+int ezgdal_load_stripe_data(EZGDAL_STRIPE *stripe, int row1) { |
|
706 |
+ int r, n, f; |
|
707 |
+ double *p; |
|
708 |
+ |
|
709 |
+ if(stripe == NULL) return 0; |
|
710 |
+ /* nothing to do */ |
|
711 |
+ if(row1 == stripe->row1) return 0; |
|
712 |
+ |
|
713 |
+ /* out of range */ |
|
714 |
+ if(row1<-stripe->rows || row1>stripe->layer->rows-1) return 0; |
|
715 |
+ |
|
716 |
+ |
|
717 |
+ p=stripe->layer->buffer; |
|
718 |
+ for(r=0; r<stripe->rows; r++) { |
|
719 |
+ stripe->layer->buffer = stripe->buffer[r] + stripe->rows; |
|
720 |
+ ezgdal_read_buffer(stripe->layer, r + row1); |
|
721 |
+ } |
|
722 |
+ stripe->layer->buffer = p; |
|
723 |
+ n = stripe->rows; |
|
724 |
+return n; |
|
725 |
+ |
|
726 |
+ |
|
727 |
+ if(row1 < stripe->row1 - stripe->rows || |
|
728 |
+ row1 > stripe->row2) { |
|
729 |
+ /* read all rows */ |
|
730 |
+ p=stripe->layer->buffer; |
|
731 |
+ for(r=0; r<stripe->rows; r++) { |
|
732 |
+ stripe->layer->buffer = stripe->buffer[r] + stripe->rows; |
|
733 |
+ ezgdal_read_buffer(stripe->layer, r + row1); |
|
734 |
+ } |
|
735 |
+ stripe->layer->buffer = p; |
|
736 |
+ n = stripe->rows; |
|
737 |
+ } else if(row1 > stripe->row1) { |
|
738 |
+ /* shift up and read only bottom */ |
|
739 |
+ n = stripe->row2 -row1 + 1; |
|
740 |
+ for(r=0; r<n; r++) { |
|
741 |
+ p = stripe->buffer[r]; |
|
742 |
+ stripe->buffer[r] = stripe->buffer[stripe->rows - n + r]; |
|
743 |
+ stripe->buffer[stripe->rows - n + r] = p; |
|
744 |
+ } |
|
745 |
+ p=stripe->layer->buffer; |
|
746 |
+ for(r=n; r<stripe->rows; r++) { |
|
747 |
+ stripe->layer->buffer = stripe->buffer[r] + stripe->rows; |
|
748 |
+ ezgdal_read_buffer(stripe->layer,r + row1); |
|
749 |
+ } |
|
750 |
+ stripe->layer->buffer = p; |
|
751 |
+ reset_frame_buffer_pointers(stripe); |
|
752 |
+ n = stripe->rows-n; |
|
753 |
+ } else { |
|
754 |
+ /* shift down and read only top */ |
|
755 |
+ n = row1 - stripe->row1 + 1; |
|
756 |
+ for(r=0; r<n; r++) { |
|
757 |
+ p = stripe->buffer[stripe->rows - n + r]; |
|
758 |
+ stripe->buffer[stripe->rows - n + r] = stripe->buffer[r]; |
|
759 |
+ stripe->buffer[r] = p; |
|
760 |
+ } |
|
761 |
+ p=stripe->layer->buffer; |
|
762 |
+ for(r=0; r<n; r++) { |
|
763 |
+ stripe->layer->buffer = stripe->buffer[r] + stripe->rows; |
|
764 |
+ ezgdal_read_buffer(stripe->layer, r + row1); |
|
765 |
+ } |
|
766 |
+ stripe->layer->buffer = p; |
|
767 |
+ reset_frame_buffer_pointers(stripe); |
|
768 |
+ } |
|
769 |
+ stripe->row1 = row1; |
|
770 |
+ stripe->row2 = row1 + stripe->rows - 1; |
|
771 |
+ |
|
772 |
+ for(f=0; f<stripe->frames; f++) { |
|
773 |
+ stripe->frame[f].row1 = stripe->row1; |
|
774 |
+ stripe->frame[f].row2 = stripe->row2; |
|
775 |
+ } |
|
776 |
+ |
|
777 |
+ return n; |
|
778 |
+} |
|
779 |
+ |
|
780 |
+int ezgdal_save_stripe_data(EZGDAL_STRIPE *stripe) { |
|
781 |
+ int row1, row2, N, buf_row = 0; |
|
782 |
+ double *p; |
|
783 |
+ |
|
784 |
+ if(stripe->row1<0) { |
|
785 |
+ buf_row=-stripe->row1; |
|
786 |
+ row1 = 0; |
|
787 |
+ } else |
|
788 |
+ row1 = stripe->row1; |
|
789 |
+ |
|
790 |
+ if(stripe->row2>=stripe->layer->rows) |
|
791 |
+ row2 = stripe->layer->rows-1; |
|
792 |
+ else |
|
793 |
+ row2 = stripe->row2; |
|
794 |
+ |
|
795 |
+ p=stripe->layer->buffer; |
|
796 |
+ N = 0; |
|
797 |
+ while(row1<=row2) { |
|
798 |
+ stripe->layer->buffer = stripe->buffer[buf_row++] + stripe->rows; |
|
799 |
+ ezgdal_write_buffer(stripe->layer,row1); |
|
800 |
+ row1++; |
|
801 |
+ N++; |
|
802 |
+ } |
|
803 |
+ stripe->layer->buffer = p; |
|
804 |
+ return N; |
|
805 |
+} |
|
806 |
+ |
|
807 |
+ |
|
808 |
+/*==========================================*/ |
|
809 |
+/* FRAMESET & FRAME */ |
|
810 |
+/* */ |
|
811 |
+ |
|
812 |
+void ezgdal_unload_frameset_frame_data(EZGDAL_FRAME *frame) { |
|
813 |
+ if(frame->private_buffer!=NULL) { |
|
814 |
+ CPLFree(frame->private_buffer); |
|
815 |
+ free(frame->buffer); |
|
816 |
+ frame->private_buffer = NULL; |
|
817 |
+ frame->buffer = NULL; |
|
818 |
+ } |
|
819 |
+} |
|
820 |
+ |
|
821 |
+void ezgdal_frameset_frame_alloc(EZGDAL_FRAME *frame) { |
|
822 |
+ int i; |
|
823 |
+ |
|
824 |
+ ezgdal_unload_frameset_frame_data(frame); |
|
825 |
+ |
|
826 |
+ unsigned long size = (unsigned long)(frame->col2-frame->col1+1)*(frame->row2-frame->row1+1); |
|
827 |
+ frame->private_buffer = (double *)CPLMalloc(size*sizeof(double)); |
|
828 |
+ |
|
829 |
+ frame->buffer = (double **)malloc(frame->rows*sizeof(double *)); |
|
830 |
+ |
|
831 |
+ if(frame->buffer==NULL || frame->private_buffer==NULL) { |
|
832 |
+ ezgdal_show_message(stderr,"No RAM to proceed!"); |
|
833 |
+ exit(EXIT_FAILURE); |
|
834 |
+ } |
|
835 |
+ |
|
836 |
+ for(i=0; i<frame->rows; i++) |
|
837 |
+ frame->buffer[i] = frame->private_buffer + i*frame->cols; |
|
838 |
+} |
|
839 |
+ |
|
840 |
+ |
|
841 |
+EZGDAL_FRAMESET* ezgdal_create_frameset_with_size(EZGDAL_LAYER *layer, int size) { |
|
842 |
+ EZGDAL_FRAMESET *fst = (EZGDAL_FRAMESET *)calloc(1,sizeof(EZGDAL_FRAMESET)); |
|
843 |
+ fst->frame = (EZGDAL_FRAME **)calloc(size,sizeof(EZGDAL_FRAME *)); |
|
844 |
+ fst->frameset_len = size; |
|
845 |
+ fst->frames = 0; |
|
846 |
+ fst->layer = layer; |
|
847 |
+ layer->frameset = fst; |
|
848 |
+ return fst; |
|
849 |
+} |
|
850 |
+ |
|
851 |
+EZGDAL_FRAMESET* ezgdal_create_frameset(EZGDAL_LAYER *layer) { |
|
852 |
+ return ezgdal_create_frameset_with_size(layer,EZGDAL_FRAMESET_LEN); |
|
853 |
+} |
|
854 |
+ |
|
855 |
+void ezgdal_frameset_max_buffer_size(unsigned long size) { |
|
856 |
+ if(size>0) max_frame_buffer_size = size; |
|
857 |
+} |
|
858 |
+ |
|
859 |
+EZGDAL_FRAME* ezgdal_add_frameset_frame(EZGDAL_FRAMESET *frameset, int col1, int col2, int row1, int row2) { |
|
860 |
+ int p; |
|
861 |
+ |
|
862 |
+ if(col1>col2) { p = col1; col1 = col2; col2 = p;} |
|
863 |
+ if(row1>row2) { p = col1; col1 = col2; col2 = p;} |
|
864 |
+ |
|
865 |
+ unsigned long size = (unsigned long)(col2-col1+1)*(row2-row1+1)*sizeof(double); |
|
866 |
+ |
|
867 |
+ if(size<=0 || size>max_frame_buffer_size) |
|
868 |
+ return NULL; |
|
869 |
+ |
|
870 |
+ EZGDAL_FRAME *frame = (EZGDAL_FRAME *)malloc(sizeof(EZGDAL_FRAME)); |
|
871 |
+ frame->owner.frameset = frameset; |
|
872 |
+ frame->private_buffer = NULL; |
|
873 |
+ frame->buffer = NULL; |
|
874 |
+ |
|
875 |
+ ezgdal_frameset_set_frame(frame, col1, col2, row1, row2); |
|
876 |
+ |
|
877 |
+ if(frameset->frames==frameset->frameset_len) { |
|
878 |
+ frameset->frameset_len += EZGDAL_FRAMESET_STEP; |
|
879 |
+ frameset->frame = realloc(frameset->frame, frameset->frameset_len); |
|
880 |
+ if(frameset->frame==NULL) { |
|
881 |
+ ezgdal_show_message(stderr,"No RAM to proceed!"); |
|
882 |
+ exit(EXIT_FAILURE); |
|
883 |
+ } |
|
884 |
+ } |
|
885 |
+ frameset->frame[frameset->frames] = frame; |
|
886 |
+ frameset->frames++; |
|
887 |
+ |
|
888 |
+ return frame; |
|
889 |
+} |
|
890 |
+ |
|
891 |
+void ezgdal_frameset_set_frame(EZGDAL_FRAME *frame, int col1, int col2, int row1, int row2) { |
|
892 |
+ int p; |
|
893 |
+ int data_are_loaded; |
|
894 |
+ |
|
895 |
+ if(frame==NULL) return; |
|
896 |
+ |
|
897 |
+ data_are_loaded = (frame->private_buffer!=NULL); |
|
898 |
+ ezgdal_unload_frameset_frame_data(frame); |
|
899 |
+ |
|
900 |
+ if(col1>col2) { p = col1; col1 = col2; col2 = p;} |
|
901 |
+ if(row1>row2) { p = row1; row1 = row2; row2 = p;} |
|
902 |
+ |
|
903 |
+ frame->col1 = col1; |
|
904 |
+ frame->col2 = col2; |
|
905 |
+ frame->row1 = row1; |
|
906 |
+ frame->row2 = row2; |
|
907 |
+ frame->cols = col2-col1+1; |
|
908 |
+ frame->rows = row2-row1+1; |
|
909 |
+ |
|
910 |
+ if(data_are_loaded) |
|
911 |
+ ezgdal_load_frameset_frame_data(frame); |
|
912 |
+} |
|
913 |
+ |
|
914 |
+void ezgdal_free_frameset(EZGDAL_FRAMESET *frameset) { |
|
915 |
+ if(frameset==NULL) return; |
|
916 |
+ EZGDAL_LAYER *l = frameset->layer; |
|
917 |
+ ezgdal_free_frameset_all_frames(frameset); |
|
918 |
+ free(frameset->frame); |
|
919 |
+ free(frameset); |
|
920 |
+ l->frameset = NULL; |
|
921 |
+} |
|
922 |
+ |
|
923 |
+void ezgdal_free_frameset_frame(EZGDAL_FRAME *frame) { |
|
924 |
+ if(frame!=NULL) { |
|
925 |
+ ezgdal_unload_frameset_frame_data(frame); |
|
926 |
+ free(frame); |
|
927 |
+ } |
|
928 |
+} |
|
929 |
+ |
|
930 |
+void ezgdal_free_frameset_all_frames(EZGDAL_FRAMESET *frameset) { |
|
931 |
+ int i; |
|
932 |
+ for(i=0; i<frameset->frames; i++) |
|
933 |
+ ezgdal_free_frameset_frame(frameset->frame[i]); |
|
934 |
+ frameset->frames = 0; |
|
935 |
+} |
|
936 |
+ |
|
937 |
+EZGDAL_FRAME* ezgdal_get_frameset_frame(EZGDAL_FRAMESET *frameset, int idx) { |
|
938 |
+ EZGDAL_FRAME *frame = NULL; |
|
939 |
+ if(idx<frameset->frames && idx>=0) |
|
940 |
+ frame = frameset->frame[idx]; |
|
941 |
+ return frame; |
|
942 |
+} |
|
943 |
+ |
|
944 |
+void ezgdal_load_frameset_frame_data(EZGDAL_FRAME *frame) { |
|
945 |
+ |
|
946 |
+ if(frame==NULL) return; |
|
947 |
+ ezgdal_frameset_frame_alloc(frame); |
|
948 |
+ |
|
949 |
+ EZGDAL_LAYER *l = frame->owner.frameset->layer; |
|
950 |
+ |
|
951 |
+ if(frame->col1 >= 0 && |
|
952 |
+ frame->row1 >= 0 && |
|
953 |
+ frame->col2 < l->cols && |
|
954 |
+ frame->row2 < l->rows) { |
|
955 |
+ // inside - read |
|
956 |
+ CPLErr res = GDALRasterIO(l->band_h, |
|
957 |
+ GF_Read, |
|
958 |
+ frame->col1, frame->row1, |
|
959 |
+ frame->cols, frame->rows, |
|
960 |
+ frame->private_buffer, |
|
961 |
+ frame->cols, frame->rows, |
|
962 |
+ GDT_Float64, 0, 0 ); |
|
963 |
+ |
|
964 |
+ if(res>CE_Warning) { |
|
965 |
+ ezgdal_show_message(stderr,"GDAL I/O operation faild!"); |
|
966 |
+ exit(EXIT_FAILURE); |
|
967 |
+ } |
|
968 |
+ |
|
969 |
+ } else { |
|
970 |
+ if(!(frame->col1 >= l->cols || |
|
971 |
+ frame->row1 >= l->rows || |
|
972 |
+ frame->col2 < 0 || frame->row2 < 0)) { |
|
973 |
+ // border crossing - read part and copy |
|
974 |
+ |
|
975 |
+ int row, col, r, c, new_c1, new_r1, new_c2, new_r2, new_cols, new_rows; |
|
976 |
+ |
|
977 |
+ int i; |
|
978 |
+ long n; |
|
979 |
+ double *p; |
|
980 |
+ |
|
981 |
+ n = frame->cols*frame->rows; |
|
982 |
+ double d = 0.0; |
|
983 |
+ if(l->is_no_data) |
|
984 |
+ d = l->no_data; |
|
985 |
+ else if(l->stats!=NULL) { |
|
986 |
+ if(l->stats->min<=0.0 && l->stats->max>=0.0) |
|
987 |
+ d = 0.0; |
|
988 |
+ else |
|
989 |
+ d = l->stats->min; |
|
990 |
+ } |
|
991 |
+ p = frame->private_buffer; |
|
992 |
+ for(i=0; i<n; i++) |
|
993 |
+ *(p++) = d; |
|
994 |
+ |
|
995 |
+ new_c1 = (frame->col1<0)?0:frame->col1; |
|
996 |
+ new_r1 = (frame->row1<0)?0:frame->row1; |
|
997 |
+ new_c2 = (frame->col2>=l->cols)?l->cols-1:frame->col2; |
|
998 |
+ new_r2 = (frame->row2>=l->rows)?l->rows-1:frame->row2; |
|
999 |
+ new_cols = new_c2 - new_c1 + 1; |
|
1000 |
+ new_rows = new_r2 - new_r1 + 1; |
|
1001 |
+ double *buf = (double *)malloc(new_cols*new_rows*sizeof(double)); |
|
1002 |
+ |
|
1003 |
+ CPLErr res = GDALRasterIO(l->band_h, |
|
1004 |
+ GF_Read, |
|
1005 |
+ new_c1, new_r1, |
|
1006 |
+ new_cols, new_rows, |
|
1007 |
+ buf, |
|
1008 |
+ new_cols, new_rows, |
|
1009 |
+ GDT_Float64, 0, 0); |
|
1010 |
+ |
|
1011 |
+ if(res>CE_Warning) { |
|
1012 |
+ free(buf); |
|
1013 |
+ ezgdal_show_message(stderr,"GDAL I/O operation faild!"); |
|
1014 |
+ exit(EXIT_FAILURE); |
|
1015 |
+ } |
|
1016 |
+ |
|
1017 |
+ for(r=0; r<new_rows; r++) { |
|
1018 |
+ row = new_r1 - frame->row1 + r; |
|
1019 |
+ col = new_c1 - frame->col1; |
|
1020 |
+ for(c=0; c<new_cols; c++) |
|
1021 |
+ frame->private_buffer[row*frame->cols+col+c] = buf[r*new_cols+c]; |
|
1022 |
+ row += frame->cols; |
|
1023 |
+ } |
|
1024 |
+ |
|
1025 |
+ free(buf); |
|
1026 |
+ } |
|
1027 |
+ } |
|
1028 |
+ |
|
1029 |
+} |
|
1030 |
+ |
... | ... |
@@ -0,0 +1,196 @@ |
1 |
+#ifndef _EZGDAL_H_ |
|
2 |
+#define _EZGDAL_H_ |
|
3 |
+ |
|
4 |
+/**************************************************************************** |
|
5 |
+ * |
|
6 |
+ * LIBRARY: ezGDAL - easy GDAL access |
|
7 |
+ * AUTHOR(S): Pawel Netzel |
|
8 |
+ * PURPOSE: library for reading GDAL layers, writting GeoTIFFs, processing |
|
9 |
+ * data row-by-row, stripe-by-stripe, frame-by-frame |
|
10 |
+ * COPYRIGHT: (C) Pawel Netzel |
|
11 |
+ * http://pawel.netzel.pl |
|
12 |
+ * |
|
13 |
+ * This program is free software under the GNU Lesser General |
|
14 |
+ * Public License (>=v3). Read the file lgpl-3.0.txt |
|
15 |
+ * |
|
16 |
+ *****************************************************************************/ |
|
17 |
+ |
|
18 |
+#include <stdio.h> |
|
19 |
+#include <gdal.h> |
|
20 |
+ |
|
21 |
+#ifdef _MSC_VER |
|
22 |
+ #ifdef DLL_EXPORT |
|
23 |
+ #define EZGDAL_DLL_API __declspec(dllexport) |
|
24 |
+ #else |
|
25 |
+ #define EZGDAL_DLL_API __declspec(dllimport) |
|
26 |
+ #endif |
|
27 |
+#else |
|
28 |
+ #define EZGDAL_DLL_API |
|
29 |
+#endif |
|
30 |
+ |
|
31 |
+#ifdef __cplusplus |
|
32 |
+extern "C" { |
|
33 |
+#endif |
|
34 |
+ |
|
35 |
+ |
|
36 |
+#define EZGDAL_FRAMESET_LEN 10240 |
|
37 |
+#define EZGDAL_FRAMESET_STEP 10240 |
|
38 |
+#define MAX_FRAME_BUFFER_SIZE 4294967295 |
|
39 |
+ |
|
40 |
+#define EZGDAL_COMPRESS_NONE 0 |
|
41 |
+#define EZGDAL_COMPRESS_DEFLATE 1 |
|
42 |
+#define EZGDAL_COMPRESS_LZW 2 |
|
43 |
+ |
|
44 |
+typedef struct { |
|
45 |
+ double min,max,avg,std; |
|
46 |
+ double hist_min,hist_max,hist_step; |
|
47 |
+ int hist_N; |
|
48 |
+ int map_max_val; |
|
49 |
+ int *map_cat; |
|
50 |
+ GUIntBig *hist; |
|
51 |
+} EZGDAL_STATS; |
|
52 |
+ |
|
53 |
+typedef struct EZGDAL_STRIPE EZGDAL_STRIPE; |
|
54 |
+typedef struct EZGDAL_FRAMESET EZGDAL_FRAMESET; |
|
55 |
+typedef struct EZGDAL_LAYER EZGDAL_LAYER; |
|
56 |
+ |
|
57 |
+union EZGDAL_FRAME_OWNER { |
|
58 |
+ EZGDAL_STRIPE *stripe; |
|
59 |
+ EZGDAL_FRAMESET *frameset; |
|
60 |
+}; |
|
61 |
+ |
|
62 |
+typedef struct { |
|
63 |
+ union EZGDAL_FRAME_OWNER owner; |
|
64 |
+ int cols, rows; |
|
65 |
+ int col1, col2; |
|
66 |
+ int row1, row2; |
|
67 |
+ double *private_buffer; |
|
68 |
+ double **buffer; |
|
69 |
+} EZGDAL_FRAME; |
|
70 |
+ |
|
71 |
+struct EZGDAL_FRAMESET { |
|
72 |
+ EZGDAL_LAYER *layer; |
|
73 |
+ int frames; |
|
74 |
+ int frameset_len; |
|
75 |
+ EZGDAL_FRAME **frame; |
|
76 |
+}; |
|
77 |
+ |
|
78 |
+struct EZGDAL_STRIPE { |
|
79 |
+ EZGDAL_LAYER *layer; |
|
80 |
+ int row1, row2; |
|
81 |
+ int rows; |
|
82 |
+ double **buffer; |
|
83 |
+ int frames; |
|
84 |
+ EZGDAL_FRAME *frame; |
|
85 |
+}; |
|
86 |
+ |
|
87 |
+struct EZGDAL_LAYER { |
|
88 |
+ GDALDatasetH dataset_h; |
|
89 |
+ GDALRasterBandH band_h; |
|
90 |
+ int rows; |
|
91 |
+ int cols; |
|
92 |
+ int is_no_data; |
|
93 |
+ double no_data; |
|
94 |
+ double *buffer; |
|
95 |
+ EZGDAL_STRIPE *stripe; |
|
96 |
+ EZGDAL_FRAMESET *frameset; |
|
97 |
+ EZGDAL_STATS *stats; |
|
98 |
+}; |
|
99 |
+ |
|
100 |
+/*==========================================*/ |
|
101 |
+/* TOOLS */ |
|
102 |
+ |
|
103 |
+EZGDAL_DLL_API double ezgdal_get_value(double *array, int idx); |
|
104 |
+EZGDAL_DLL_API void ezgdal_set_value(double *array, int idx, double val); |
|
105 |
+ |
|
106 |
+EZGDAL_DLL_API int ezgdal_file_exists(const char *fname); |
|
107 |
+EZGDAL_DLL_API void ezgdal_show_progress(FILE *f, int i, int N); |
|
108 |
+EZGDAL_DLL_API void ezgdal_show_message(FILE *f, char *message); |
|
109 |
+EZGDAL_DLL_API void ezgdal_show_message_nolf(FILE *f, char *message); |
|
110 |
+ |
|
111 |
+EZGDAL_DLL_API int ezgdal_is_bbox_ok(EZGDAL_LAYER **inputs, int ninputs); |
|
112 |
+EZGDAL_DLL_API int ezgdal_is_projection_ok(EZGDAL_LAYER **inputs, int ninputs); |
|
113 |
+ |
|
114 |
+EZGDAL_DLL_API GDALDataType ezgdal_data_type(char *data); |
|
115 |
+ |
|
116 |
+EZGDAL_DLL_API int ezgdal_xy2c(EZGDAL_LAYER *layer, double x, double y); |
|
117 |
+EZGDAL_DLL_API double ezgdal_cr2x(EZGDAL_LAYER *layer, int col, int row); |
|
118 |
+EZGDAL_DLL_API int ezgdal_xy2r(EZGDAL_LAYER *layer, double x, double y); |
|
119 |
+EZGDAL_DLL_API double ezgdal_cr2y(EZGDAL_LAYER *layer, int col, int row); |
|
120 |
+ |
|
121 |
+/*==========================================*/ |
|
122 |
+/* EZGDAL_LAYER */ |
|
123 |
+ |
|
124 |
+EZGDAL_DLL_API EZGDAL_LAYER* ezgdal_create_layer(char *fname, |
|
125 |
+ char *wkt, |
|
126 |
+ char *d_type, |
|
127 |
+ double *geo_tr, |
|
128 |
+ int rows, |
|
129 |
+ int cols, |
|
130 |
+ int *nodata, |
|
131 |
+ int compress); |
|
132 |
+EZGDAL_DLL_API EZGDAL_LAYER* ezgdal_open_layer(char *fname); |
|
133 |
+EZGDAL_DLL_API EZGDAL_LAYER* ezgdal_open_layer_band(char *fname, int band); |
|
134 |
+EZGDAL_DLL_API EZGDAL_LAYER* ezgdal_open_layer_rw(char *fname); |
|
135 |
+EZGDAL_DLL_API void ezgdal_close_layer(EZGDAL_LAYER *layer); |
|
136 |
+ |
|
137 |
+EZGDAL_DLL_API void ezgdal_set_palette255(EZGDAL_LAYER *layer, double palette[][5], int n); |
|
138 |
+ |
|
139 |
+EZGDAL_DLL_API void ezgdal_read_buffer(EZGDAL_LAYER *layer, int row); |
|
140 |
+EZGDAL_DLL_API void ezgdal_write_buffer(EZGDAL_LAYER *layer, int row); |
|
141 |
+ |
|
142 |
+EZGDAL_DLL_API void ezgdal_read_all_layer(EZGDAL_LAYER *layer, double* buffer); |
|
143 |
+EZGDAL_DLL_API void ezgdal_write_all_layer(EZGDAL_LAYER *layer, double* buffer); |
|
144 |
+ |
|
145 |
+EZGDAL_DLL_API char* ezgdal_layer_get_wkt(EZGDAL_LAYER *layer); |
|
146 |
+EZGDAL_DLL_API double* ezgdal_layer_get_at(EZGDAL_LAYER *layer); |
|
147 |
+ |
|
148 |
+EZGDAL_DLL_API int ezgdal_is_null(EZGDAL_LAYER *layer, double v); |
|
149 |
+EZGDAL_DLL_API void ezgdal_set_null(EZGDAL_LAYER *layer, double *v); |
|
150 |
+ |
|
151 |
+/*==========================================*/ |
|
152 |
+/* STATS */ |
|
153 |
+ |
|
154 |
+EZGDAL_DLL_API void ezgdal_calc_layer_stats(EZGDAL_LAYER *layer); |
|
155 |
+EZGDAL_DLL_API void ezgdal_calc_value_map(EZGDAL_LAYER *layer, double min, double max, int N); |
|
156 |
+EZGDAL_DLL_API int ezgdal_get_value_index(EZGDAL_LAYER *layer, double val); |
|
157 |
+EZGDAL_DLL_API double ezgdal_get_index_value(EZGDAL_LAYER *layer, int idx); |
|
158 |
+ |
|
159 |
+/*==========================================*/ |
|
160 |
+/* STRIPE & FRAME */ |
|
161 |
+ |
|
162 |
+EZGDAL_DLL_API EZGDAL_STRIPE* ezgdal_create_stripe(EZGDAL_LAYER *layer, int row1, int height); |
|
163 |
+EZGDAL_DLL_API EZGDAL_FRAME* ezgdal_create_frame(EZGDAL_STRIPE *stripe, int col1); |
|
164 |
+EZGDAL_DLL_API int ezgdal_create_all_frames(EZGDAL_STRIPE *stripe, int start, int shift); |
|
165 |
+EZGDAL_DLL_API void ezgdal_free_stripe(EZGDAL_LAYER *layer); |
|
166 |
+EZGDAL_DLL_API void ezgdal_free_all_frames(EZGDAL_STRIPE *stripe); |
|
167 |
+ |
|
168 |
+EZGDAL_DLL_API EZGDAL_FRAME* ezgdal_get_frame(EZGDAL_STRIPE *stripe, int idx); |
|
169 |
+EZGDAL_DLL_API void ezgdal_shift_frame_pos(EZGDAL_FRAME *frame, int col); |
|
170 |
+ |
|
171 |
+EZGDAL_DLL_API int ezgdal_load_stripe_data(EZGDAL_STRIPE *stripe, int row1); |
|
172 |
+EZGDAL_DLL_API int ezgdal_save_stripe_data(EZGDAL_STRIPE *stripe); |
|
173 |
+ |
|
174 |
+/*==========================================*/ |
|
175 |
+/* FRAMESET & FRAME */ |
|
176 |
+ |
|
177 |
+EZGDAL_DLL_API void ezgdal_frameset_max_buffer_size(unsigned long size); |
|
178 |
+EZGDAL_DLL_API EZGDAL_FRAMESET* ezgdal_create_frameset(EZGDAL_LAYER *layer); |
|
179 |
+EZGDAL_DLL_API EZGDAL_FRAMESET* ezgdal_create_frameset_with_size(EZGDAL_LAYER *layer, int size); |
|
180 |
+EZGDAL_DLL_API EZGDAL_FRAME* ezgdal_add_frameset_frame(EZGDAL_FRAMESET *frameset, int col1, int col2, int row1, int row2); |
|
181 |
+EZGDAL_DLL_API void ezgdal_frameset_set_frame(EZGDAL_FRAME *frame, int col1, int col2, int row1, int row2); |
|
182 |
+EZGDAL_DLL_API void ezgdal_free_frameset(EZGDAL_FRAMESET *frameset); |
|
183 |
+EZGDAL_DLL_API void ezgdal_free_frameset_frame(EZGDAL_FRAME *frame); |
|
184 |
+EZGDAL_DLL_API void ezgdal_free_frameset_all_frames(EZGDAL_FRAMESET *frameset); |
|
185 |
+ |
|
186 |
+EZGDAL_DLL_API EZGDAL_FRAME* ezgdal_get_frameset_frame(EZGDAL_FRAMESET *frameset, int idx); |
|
187 |
+EZGDAL_DLL_API void ezgdal_load_frameset_frame_data(EZGDAL_FRAME *frame); |
|
188 |
+EZGDAL_DLL_API void ezgdal_unload_frameset_frame_data(EZGDAL_FRAME *frame); |
|
189 |
+ |
|
190 |
+#ifdef __cplusplus |
|
191 |
+} |
|
192 |
+#endif |
|
193 |
+ |
|
194 |
+ |
|
195 |
+#endif |
|
196 |
+ |
... | ... |
@@ -0,0 +1,165 @@ |
1 |
+ GNU LESSER GENERAL PUBLIC LICENSE |
|
2 |
+ Version 3, 29 June 2007 |
|
3 |
+ |
|
4 |
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|
5 |
+ Everyone is permitted to copy and distribute verbatim copies |
|
6 |
+ of this license document, but changing it is not allowed. |
|
7 |
+ |
|
8 |
+ |
|
9 |
+ This version of the GNU Lesser General Public License incorporates |
|
10 |
+the terms and conditions of version 3 of the GNU General Public |
|
11 |
+License, supplemented by the additional permissions listed below. |
|
12 |
+ |
|
13 |
+ 0. Additional Definitions. |
|
14 |
+ |
|
15 |
+ As used herein, "this License" refers to version 3 of the GNU Lesser |
|
16 |
+General Public License, and the "GNU GPL" refers to version 3 of the GNU |
|
17 |
+General Public License. |
|
18 |
+ |
|
19 |
+ "The Library" refers to a covered work governed by this License, |
|
20 |
+other than an Application or a Combined Work as defined below. |
|
21 |
+ |
|
22 |
+ An "Application" is any work that makes use of an interface provided |
|
23 |
+by the Library, but which is not otherwise based on the Library. |
|
24 |
+Defining a subclass of a class defined by the Library is deemed a mode |
|
25 |
+of using an interface provided by the Library. |
|
26 |
+ |
|
27 |
+ A "Combined Work" is a work produced by combining or linking an |
|
28 |
+Application with the Library. The particular version of the Library |
|
29 |
+with which the Combined Work was made is also called the "Linked |
|
30 |
+Version". |
|
31 |
+ |
|
32 |
+ The "Minimal Corresponding Source" for a Combined Work means the |
|
33 |
+Corresponding Source for the Combined Work, excluding any source code |
|
34 |
+for portions of the Combined Work that, considered in isolation, are |
|
35 |
+based on the Application, and not on the Linked Version. |
|
36 |
+ |
|
37 |
+ The "Corresponding Application Code" for a Combined Work means the |
|
38 |
+object code and/or source code for the Application, including any data |
|
39 |
+and utility programs needed for reproducing the Combined Work from the |
|
40 |
+Application, but excluding the System Libraries of the Combined Work. |
|
41 |
+ |
|
42 |
+ 1. Exception to Section 3 of the GNU GPL. |
|
43 |
+ |
|
44 |
+ You may convey a covered work under sections 3 and 4 of this License |
|
45 |
+without being bound by section 3 of the GNU GPL. |
|
46 |
+ |
|
47 |
+ 2. Conveying Modified Versions. |
|
48 |
+ |
|
49 |
+ If you modify a copy of the Library, and, in your modifications, a |
|
50 |
+facility refers to a function or data to be supplied by an Application |
|
51 |
+that uses the facility (other than as an argument passed when the |
|
52 |
+facility is invoked), then you may convey a copy of the modified |
|
53 |
+version: |
|
54 |
+ |
|
55 |
+ a) under this License, provided that you make a good faith effort to |
|
56 |
+ ensure that, in the event an Application does not supply the |
|
57 |
+ function or data, the facility still operates, and performs |
|
58 |
+ whatever part of its purpose remains meaningful, or |
|
59 |
+ |
|
60 |
+ b) under the GNU GPL, with none of the additional permissions of |
|
61 |
+ this License applicable to that copy. |
|
62 |
+ |
|
63 |
+ 3. Object Code Incorporating Material from Library Header Files. |
|
64 |
+ |
|
65 |
+ The object code form of an Application may incorporate material from |
|
66 |
+a header file that is part of the Library. You may convey such object |
|
67 |
+code under terms of your choice, provided that, if the incorporated |
|
68 |
+material is not limited to numerical parameters, data structure |
|
69 |
+layouts and accessors, or small macros, inline functions and templates |
|
70 |
+(ten or fewer lines in length), you do both of the following: |
|
71 |
+ |
|
72 |
+ a) Give prominent notice with each copy of the object code that the |
|
73 |
+ Library is used in it and that the Library and its use are |
|
74 |
+ covered by this License. |
|
75 |
+ |
|
76 |
+ b) Accompany the object code with a copy of the GNU GPL and this license |
|
77 |
+ document. |
|
78 |
+ |
|
79 |
+ 4. Combined Works. |
|
80 |
+ |
|
81 |
+ You may convey a Combined Work under terms of your choice that, |
|
82 |
+taken together, effectively do not restrict modification of the |
|
83 |
+portions of the Library contained in the Combined Work and reverse |
|
84 |
+engineering for debugging such modifications, if you also do each of |
|
85 |
+the following: |
|
86 |
+ |
|
87 |
+ a) Give prominent notice with each copy of the Combined Work that |
|
88 |
+ the Library is used in it and that the Library and its use are |
|
89 |
+ covered by this License. |
|
90 |
+ |
|
91 |
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license |
|
92 |
+ document. |
|
93 |
+ |
|
94 |
+ c) For a Combined Work that displays copyright notices during |
|
95 |
+ execution, include the copyright notice for the Library among |
|
96 |
+ these notices, as well as a reference directing the user to the |
|
97 |
+ copies of the GNU GPL and this license document. |
|
98 |
+ |
|
99 |
+ d) Do one of the following: |
|
100 |
+ |
|
101 |
+ 0) Convey the Minimal Corresponding Source under the terms of this |
|
102 |
+ License, and the Corresponding Application Code in a form |
|
103 |
+ suitable for, and under terms that permit, the user to |
|
104 |
+ recombine or relink the Application with a modified version of |
|
105 |
+ the Linked Version to produce a modified Combined Work, in the |
|
106 |
+ manner specified by section 6 of the GNU GPL for conveying |
|
107 |
+ Corresponding Source. |
|
108 |
+ |
|
109 |
+ 1) Use a suitable shared library mechanism for linking with the |
|
110 |
+ Library. A suitable mechanism is one that (a) uses at run time |
|
111 |
+ a copy of the Library already present on the user's computer |
|
112 |
+ system, and (b) will operate properly with a modified version |
|
113 |
+ of the Library that is interface-compatible with the Linked |
|
114 |
+ Version. |
|
115 |
+ |
|
116 |
+ e) Provide Installation Information, but only if you would otherwise |
|
117 |
+ be required to provide such information under section 6 of the |
|
118 |
+ GNU GPL, and only to the extent that such information is |
|
119 |
+ necessary to install and execute a modified version of the |
|
120 |
+ Combined Work produced by recombining or relinking the |
|
121 |
+ Application with a modified version of the Linked Version. (If |
|
122 |
+ you use option 4d0, the Installation Information must accompany |
|
123 |
+ the Minimal Corresponding Source and Corresponding Application |
|
124 |
+ Code. If you use option 4d1, you must provide the Installation |
|
125 |
+ Information in the manner specified by section 6 of the GNU GPL |
|
126 |
+ for conveying Corresponding Source.) |
|
127 |
+ |
|
128 |
+ 5. Combined Libraries. |
|
129 |
+ |
|
130 |
+ You may place library facilities that are a work based on the |
|
131 |
+Library side by side in a single library together with other library |
|
132 |
+facilities that are not Applications and are not covered by this |
|
133 |
+License, and convey such a combined library under terms of your |
|
134 |
+choice, if you do both of the following: |
|
135 |
+ |
|
136 |
+ a) Accompany the combined library with a copy of the same work based |
|
137 |
+ on the Library, uncombined with any other library facilities, |
|
138 |
+ conveyed under the terms of this License. |
|
139 |
+ |
|
140 |
+ b) Give prominent notice with the combined library that part of it |
|
141 |
+ is a work based on the Library, and explaining where to find the |
|
142 |
+ accompanying uncombined form of the same work. |
|
143 |
+ |
|
144 |
+ 6. Revised Versions of the GNU Lesser General Public License. |
|
145 |
+ |
|
146 |
+ The Free Software Foundation may publish revised and/or new versions |
|
147 |
+of the GNU Lesser General Public License from time to time. Such new |
|
148 |
+versions will be similar in spirit to the present version, but may |
|
149 |
+differ in detail to address new problems or concerns. |
|
150 |
+ |
|
151 |
+ Each version is given a distinguishing version number. If the |
|
152 |
+Library as you received it specifies that a certain numbered version |
|
153 |
+of the GNU Lesser General Public License "or any later version" |
|
154 |
+applies to it, you have the option of following the terms and |
|
155 |
+conditions either of that published version or of any later version |
|
156 |
+published by the Free Software Foundation. If the Library as you |
|
157 |
+received it does not specify a version number of the GNU Lesser |
|
158 |
+General Public License, you may choose any version of the GNU Lesser |
|
159 |
+General Public License ever published by the Free Software Foundation. |
|
160 |
+ |
|
161 |
+ If the Library as you received it specifies that a proxy can decide |
|
162 |
+whether future versions of the GNU Lesser General Public License shall |
|
163 |
+apply, that proxy's public statement of acceptance of any version is |
|
164 |
+permanent authorization for you to choose that version for the |
|
165 |
+Library. |
|
0 | 166 |