/src/gdal/frmts/pcraster/libcsf/create2.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "csf.h" |
2 | | #include "csfimpl.h" |
3 | | |
4 | | #include <errno.h> |
5 | | #include <string.h> |
6 | | |
7 | | /* M_PI */ |
8 | | #include <math.h> |
9 | | #ifndef M_PI |
10 | | # define M_PI ((double)3.14159265358979323846) |
11 | | #endif |
12 | | |
13 | | /* |
14 | | * Create a new CSF-Raster-file |
15 | | * The Rcreate function |
16 | | * creates a new CSF-Raster-file of nrRows by nrCols where each |
17 | | * cell is of type cellRepr. If the file already exists its |
18 | | * contents is destroyed. The value of |
19 | | * the pixels is undefined. MinMaxStatus is MM_KEEPTRACK. The |
20 | | * access mode is M_READ_WRITE. |
21 | | * It is not |
22 | | * known if a file is created after a NOSPACE message. |
23 | | * Returns |
24 | | * if the file is created successfully, Rcreate returns |
25 | | * a map handle. In case of an error Rcreate returns NULL. |
26 | | * |
27 | | * Merrno |
28 | | * NOCORE, BAD_CELLREPR, BAD_PROJECTION, OPENFAILED, NOSPACE. |
29 | | * CONFL_CELLREPR and BAD_VALUESCALE will generate a failed assertion in DEBUG mode. |
30 | | * |
31 | | * Example: |
32 | | * .so examples/create2.tr |
33 | | * |
34 | | */ |
35 | | |
36 | | MAP *Rcreate( |
37 | | const char *fileName, /* name of the file to be created */ |
38 | | size_t nrRows, /* the number of rows */ |
39 | | size_t nrCols, /* the number of columns */ |
40 | | CSF_CR cellRepr, /* the cell representation must be complaint with the data type |
41 | | */ |
42 | | CSF_VS dataType, /* a.k.a. the value scale. |
43 | | */ |
44 | | CSF_PT projection, /* |
45 | | */ |
46 | | REAL8 xUL, /* x co-ordinate of upper left */ |
47 | | REAL8 yUL, /* y co-ordinate of upper left */ |
48 | | REAL8 angle, /* counter clockwise rotation angle |
49 | | * of the grid top compared to the |
50 | | * x-axis in radians. Legal value are |
51 | | * between -0.5 pi and 0.5 pi |
52 | | */ |
53 | | REAL8 cellSize) /* cell size of pixel */ |
54 | 0 | { |
55 | 0 | MAP *newMap; |
56 | 0 | size_t fileSize; |
57 | 0 | char crap = 0; |
58 | |
|
59 | 0 | if (! CsfIsBootedCsfKernel()) |
60 | 0 | CsfBootCsfKernel(); |
61 | |
|
62 | 0 | newMap = (MAP *)CSF_MALLOC(sizeof(MAP)); |
63 | 0 | if (newMap == NULL) |
64 | 0 | { |
65 | 0 | M_ERROR(NOCORE); |
66 | 0 | goto errorMapAlloc; |
67 | 0 | } |
68 | 0 | newMap->fileName = (char *)CSF_MALLOC(strlen(fileName)+1); |
69 | 0 | if (newMap->fileName == NULL) |
70 | 0 | { |
71 | 0 | M_ERROR(NOCORE); |
72 | 0 | goto errorNameAlloc; |
73 | 0 | } |
74 | | |
75 | 0 | if (!( |
76 | 0 | cellRepr == CR_INT4 || |
77 | 0 | cellRepr == CR_UINT1 || |
78 | 0 | cellRepr == CR_REAL4 || |
79 | 0 | cellRepr == CR_REAL8 )) |
80 | 0 | { |
81 | 0 | M_ERROR(BAD_CELLREPR); |
82 | 0 | goto error_notOpen; |
83 | 0 | } |
84 | | |
85 | 0 | switch(dataType) { |
86 | 0 | case VS_BOOLEAN: |
87 | 0 | case VS_LDD: |
88 | 0 | if (cellRepr != CR_UINT1) |
89 | 0 | { |
90 | 0 | PROG_ERROR(CONFL_CELLREPR); |
91 | 0 | goto error_notOpen; |
92 | 0 | } |
93 | 0 | break; |
94 | 0 | case VS_NOMINAL: |
95 | 0 | case VS_ORDINAL: |
96 | 0 | if (IS_REAL(cellRepr)) |
97 | 0 | { |
98 | 0 | PROG_ERROR(CONFL_CELLREPR); |
99 | 0 | goto error_notOpen; |
100 | 0 | } |
101 | 0 | break; |
102 | 0 | case VS_SCALAR: |
103 | 0 | case VS_DIRECTION: |
104 | 0 | if (!IS_REAL(cellRepr)) |
105 | 0 | { |
106 | 0 | PROG_ERROR(CONFL_CELLREPR); |
107 | 0 | goto error_notOpen; |
108 | 0 | } |
109 | 0 | break; |
110 | 0 | default: |
111 | 0 | PROG_ERROR(BAD_VALUESCALE); |
112 | 0 | goto error_notOpen; |
113 | 0 | } |
114 | | |
115 | 0 | if (cellSize <= 0.0) |
116 | 0 | { |
117 | 0 | M_ERROR(ILL_CELLSIZE); |
118 | 0 | goto error_notOpen; |
119 | 0 | } |
120 | | |
121 | 0 | if ((0.5*-M_PI) >= angle || angle >= (0.5*M_PI)) |
122 | 0 | { |
123 | 0 | M_ERROR(BAD_ANGLE); |
124 | 0 | goto error_notOpen; |
125 | 0 | } |
126 | | |
127 | 0 | newMap->fileAccessMode = M_READ_WRITE; |
128 | 0 | (void)strcpy(newMap->fileName, fileName); |
129 | |
|
130 | 0 | newMap->fp = fopen (fileName, S_CREATE); |
131 | 0 | if(newMap->fp == NULL) |
132 | 0 | { |
133 | | /* we should analyse the errno parameter |
134 | | * here to get the reason |
135 | | */ |
136 | 0 | M_ERROR(OPENFAILED); |
137 | 0 | goto error_notOpen; |
138 | 0 | } |
139 | | /* |
140 | | fflush(newMap->fp); WHY? |
141 | | */ |
142 | | |
143 | 0 | (void)memset(&(newMap->main),0, sizeof(CSF_MAIN_HEADER)); |
144 | 0 | (void)memset(&(newMap->raster),0, sizeof(CSF_RASTER_HEADER)); |
145 | | /* put defaults values */ |
146 | | |
147 | | /* assure signature is padded with 0x0 */ |
148 | 0 | (void)memset(newMap->main.signature, 0x0, (size_t)CSF_SIG_SPACE); |
149 | 0 | (void)strcpy(newMap->main.signature, CSF_SIG); |
150 | 0 | newMap->main.version = CSF_VERSION_2; |
151 | 0 | newMap->main.gisFileId = 0; |
152 | 0 | newMap->main.projection = PROJ_DEC_T2B(projection); |
153 | 0 | newMap->main.attrTable = 0; /* initially no attributes */ |
154 | 0 | newMap->main.mapType = T_RASTER; |
155 | | |
156 | | /* write endian mode current machine: */ |
157 | 0 | newMap->main.byteOrder= ORD_OK; |
158 | |
|
159 | | #ifdef DEBUG |
160 | | newMap->read = (CSF_READ_FUNC)CsfReadPlain; |
161 | | newMap->write = (CSF_READ_FUNC)CsfWritePlain; |
162 | | #else |
163 | 0 | newMap->read = (CSF_READ_FUNC)fread; |
164 | 0 | newMap->write = (CSF_READ_FUNC)fwrite; |
165 | 0 | #endif |
166 | |
|
167 | 0 | newMap->raster.valueScale = dataType; |
168 | 0 | newMap->raster.cellRepr = cellRepr; |
169 | 0 | CsfSetVarTypeMV( &(newMap->raster.minVal), cellRepr); |
170 | 0 | CsfSetVarTypeMV( &(newMap->raster.maxVal), cellRepr); |
171 | 0 | newMap->raster.xUL = xUL; |
172 | 0 | newMap->raster.yUL = yUL; |
173 | 0 | newMap->raster.nrRows = (UINT4)nrRows; |
174 | 0 | newMap->raster.nrCols = (UINT4)nrCols; |
175 | 0 | newMap->raster.cellSize = cellSize; |
176 | 0 | newMap->raster.cellSizeDupl = cellSize; |
177 | 0 | newMap->raster.angle = angle; |
178 | 0 | CsfFinishMapInit(newMap); |
179 | | |
180 | | /* set types to value cellRepr |
181 | | newMap->types[STORED_AS]= (UINT1)newMap->raster.cellRepr; |
182 | | newMap->types[READ_AS] = (UINT1)newMap->raster.cellRepr; |
183 | | */ |
184 | 0 | newMap->appCR = (UINT1)newMap->raster.cellRepr; |
185 | 0 | newMap->app2file = CsfDummyConversion; |
186 | 0 | newMap->file2app = CsfDummyConversion; |
187 | | |
188 | | /* make file the size of the header and data */ |
189 | 0 | fileSize = nrRows*nrCols; |
190 | 0 | fileSize <<= LOG_CELLSIZE(cellRepr); |
191 | 0 | fileSize += ADDR_DATA; |
192 | | |
193 | | /* enlarge the file to the length needed by seeking and writing |
194 | | one byte of crap */ |
195 | |
|
196 | 0 | if ( csf_fseek(newMap->fp, fileSize-1, SEEK_SET) || /* fsetpos() is better */ |
197 | 0 | newMap->write(&crap, (size_t)1, (size_t)1, newMap->fp) != 1 ) |
198 | 0 | { |
199 | 0 | M_ERROR(NOSPACE); |
200 | 0 | goto error_open; |
201 | 0 | } |
202 | 0 | (void)fflush(newMap->fp); |
203 | 0 | if ( csf_ftell(newMap->fp) != (CSF_FADDR)fileSize) |
204 | 0 | { |
205 | 0 | M_ERROR(NOSPACE); |
206 | 0 | goto error_open; |
207 | 0 | } |
208 | | |
209 | 0 | newMap->minMaxStatus = MM_KEEPTRACK; |
210 | |
|
211 | 0 | CsfRegisterMap(newMap); |
212 | |
|
213 | 0 | return(newMap); |
214 | 0 | error_open: |
215 | 0 | (void)fclose(newMap->fp); |
216 | 0 | error_notOpen: |
217 | 0 | CSF_FREE(newMap->fileName); |
218 | 0 | errorNameAlloc: |
219 | 0 | CSF_FREE(newMap); |
220 | 0 | errorMapAlloc: |
221 | 0 | return(NULL); |
222 | 0 | } |