1 : /******************************************************************************
2 : * $Id: ogrsegydatasource.cpp 23268 2011-10-22 09:50:46Z rouault $
3 : *
4 : * Project: SEG-Y Translator
5 : * Purpose: Implements OGRSEGYDataSource class.
6 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMSEGYS OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_segy.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ogrsegydatasource.cpp 23268 2011-10-22 09:50:46Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRSEGYDataSource() */
38 : /************************************************************************/
39 :
40 23 : OGRSEGYDataSource::OGRSEGYDataSource()
41 :
42 : {
43 23 : papoLayers = NULL;
44 23 : nLayers = 0;
45 :
46 23 : pszName = NULL;
47 23 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRSEGYDataSource() */
51 : /************************************************************************/
52 :
53 23 : OGRSEGYDataSource::~OGRSEGYDataSource()
54 :
55 : {
56 25 : for( int i = 0; i < nLayers; i++ )
57 2 : delete papoLayers[i];
58 23 : CPLFree( papoLayers );
59 :
60 23 : CPLFree( pszName );
61 23 : }
62 :
63 : /************************************************************************/
64 : /* TestCapability() */
65 : /************************************************************************/
66 :
67 1 : int OGRSEGYDataSource::TestCapability( const char * pszCap )
68 :
69 : {
70 1 : return FALSE;
71 : }
72 :
73 : /************************************************************************/
74 : /* GetLayer() */
75 : /************************************************************************/
76 :
77 2 : OGRLayer *OGRSEGYDataSource::GetLayer( int iLayer )
78 :
79 : {
80 2 : if( iLayer < 0 || iLayer >= nLayers )
81 0 : return NULL;
82 : else
83 2 : return papoLayers[iLayer];
84 : }
85 :
86 : /************************************************************************/
87 : /* SEGYReadMSBInt16() */
88 : /************************************************************************/
89 :
90 80 : GInt16 SEGYReadMSBInt16(const GByte* pabyVal)
91 : {
92 : GInt16 nVal;
93 80 : memcpy(&nVal, pabyVal, 2);
94 80 : CPL_MSBPTR16(&nVal);
95 80 : return nVal;
96 : }
97 :
98 : /************************************************************************/
99 : /* SEGYReadMSBInt32() */
100 : /************************************************************************/
101 :
102 24 : GInt32 SEGYReadMSBInt32(const GByte* pabyVal)
103 : {
104 : GInt32 nVal;
105 24 : memcpy(&nVal, pabyVal, 4);
106 24 : CPL_MSBPTR32(&nVal);
107 24 : return nVal;
108 : }
109 :
110 : /************************************************************************/
111 : /* EBCDICToASCII */
112 : /************************************************************************/
113 :
114 : static const GByte EBCDICToASCII[] =
115 : {
116 : 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
117 : 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
118 : 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
119 : 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
120 : 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
121 : 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
122 : 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
123 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
124 : 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 : 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 : 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 : 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 : 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 : 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 : 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F,
132 : };
133 :
134 : /************************************************************************/
135 : /* Open() */
136 : /************************************************************************/
137 :
138 23 : int OGRSEGYDataSource::Open( const char * pszFilename, int bUpdateIn)
139 :
140 : {
141 23 : if (bUpdateIn)
142 : {
143 5 : return FALSE;
144 : }
145 :
146 18 : pszName = CPLStrdup( pszFilename );
147 :
148 18 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
149 18 : if (fp == NULL)
150 5 : return FALSE;
151 :
152 :
153 : // --------------------------------------------------------------------
154 : // Read the first 3200 bytes, where the Textual File Header is
155 : // located
156 : // --------------------------------------------------------------------
157 :
158 13 : GByte* pabyTextHeader = (GByte*) CPLMalloc(3200 + 1);
159 13 : GByte* pabyASCIITextHeader = (GByte*) CPLMalloc(3200 + 40 + 1);
160 13 : if ((int)VSIFReadL(pabyTextHeader, 1, 3200, fp) != 3200)
161 : {
162 4 : VSIFCloseL(fp);
163 4 : CPLFree(pabyTextHeader);
164 4 : CPLFree(pabyASCIITextHeader);
165 4 : return FALSE;
166 : }
167 :
168 : // --------------------------------------------------------------------
169 : // Try to decode the header encoded as EBCDIC and then ASCII
170 : // --------------------------------------------------------------------
171 :
172 : int i, j, k;
173 17 : for( k=0; k<2; k++)
174 : {
175 9773 : for( i=0, j=0;i<3200;i++)
176 : {
177 3213 : GByte chASCII = (k == 0) ? EBCDICToASCII[pabyTextHeader[i]] :
178 12983 : pabyTextHeader[i];
179 9770 : if (chASCII < 32 && chASCII != '\t' &&
180 : chASCII != '\n' && chASCII != '\r')
181 : {
182 14 : break;
183 : }
184 9756 : pabyASCIITextHeader[j++] = chASCII;
185 9756 : if (chASCII != '\n' && ((i + 1) % 80) == 0)
186 119 : pabyASCIITextHeader[j++] = '\n';
187 : }
188 17 : pabyASCIITextHeader[j] = '\0';
189 :
190 17 : if (i == 3200)
191 3 : break;
192 14 : if (k == 1)
193 : {
194 6 : VSIFCloseL(fp);
195 6 : CPLFree(pabyTextHeader);
196 6 : CPLFree(pabyASCIITextHeader);
197 6 : return FALSE;
198 : }
199 : }
200 :
201 3 : CPLDebug("SIGY", "Header = \n%s", pabyASCIITextHeader);
202 3 : CPLFree(pabyTextHeader);
203 :
204 :
205 : // --------------------------------------------------------------------
206 : // SEGYRead the next 400 bytes, where the Binary File Header is
207 : // located
208 : // --------------------------------------------------------------------
209 :
210 : GByte abyFileHeader[400];
211 3 : if ((int)VSIFReadL(abyFileHeader, 1, 400, fp) != 400)
212 : {
213 1 : VSIFCloseL(fp);
214 1 : CPLFree(pabyASCIITextHeader);
215 1 : return FALSE;
216 : }
217 :
218 : // --------------------------------------------------------------------
219 : // First check that this binary header is not EBCDIC nor ASCII
220 : // --------------------------------------------------------------------
221 4 : for( k=0;k<2;k++ )
222 : {
223 403 : for( i=0;i<400;i++)
224 : {
225 401 : GByte chASCII = (k == 0) ? abyFileHeader[i] :
226 803 : EBCDICToASCII[abyFileHeader[i]];
227 : /* A translated 0 value, when source value is not 0, means an invalid */
228 : /* EBCDIC value. Bail out also for control characters */
229 402 : if (chASCII < 32 && chASCII != '\t' &&
230 : chASCII != '\n' && chASCII != '\r')
231 : {
232 2 : break;
233 : }
234 : }
235 3 : if (i == 400)
236 : {
237 1 : VSIFCloseL(fp);
238 1 : CPLFree(pabyASCIITextHeader);
239 1 : return FALSE;
240 : }
241 : }
242 :
243 : SEGYBinaryFileHeader sBFH;
244 :
245 1 : sBFH.nJobIdNumber = SEGYReadMSBInt32(abyFileHeader + 0);
246 1 : sBFH.nLineNumber = SEGYReadMSBInt32(abyFileHeader + 4);
247 1 : sBFH.nReelNumber = SEGYReadMSBInt32(abyFileHeader + 8);
248 1 : sBFH.nDataTracesPerEnsemble = SEGYReadMSBInt16(abyFileHeader + 12);
249 1 : sBFH.nAuxTracesPerEnsemble = SEGYReadMSBInt16(abyFileHeader + 14);
250 1 : sBFH.nSampleInterval = SEGYReadMSBInt16(abyFileHeader + 16);
251 1 : sBFH.nSampleIntervalOriginal = SEGYReadMSBInt16(abyFileHeader + 18);
252 1 : sBFH.nSamplesPerDataTrace = SEGYReadMSBInt16(abyFileHeader + 20);
253 1 : sBFH.nSamplesPerDataTraceOriginal = SEGYReadMSBInt16(abyFileHeader + 22);
254 1 : sBFH.nDataSampleType = SEGYReadMSBInt16(abyFileHeader + 24);
255 1 : sBFH.nEnsembleFold = SEGYReadMSBInt16(abyFileHeader + 26);
256 1 : sBFH.nTraceSortingCode = SEGYReadMSBInt16(abyFileHeader + 28);
257 1 : sBFH.nVerticalSumCode = SEGYReadMSBInt16(abyFileHeader + 30);
258 1 : sBFH.nSweepFrequencyAtStart = SEGYReadMSBInt16(abyFileHeader + 32);
259 1 : sBFH.nSweepFrequencyAtEnd = SEGYReadMSBInt16(abyFileHeader + 34);
260 1 : sBFH.nSweepLength = SEGYReadMSBInt16(abyFileHeader + 36);
261 1 : sBFH.nSweepType = SEGYReadMSBInt16(abyFileHeader + 38);
262 1 : sBFH.nTraceNumberOfSweepChannel = SEGYReadMSBInt16(abyFileHeader + 40);
263 1 : sBFH.nSweepTraceTaperLengthAtStart = SEGYReadMSBInt16(abyFileHeader + 42);
264 1 : sBFH.nSweepTraceTaperLengthAtEnd = SEGYReadMSBInt16(abyFileHeader + 44);
265 1 : sBFH.nTaperType = SEGYReadMSBInt16(abyFileHeader + 46);
266 1 : sBFH.nCorrelated = SEGYReadMSBInt16(abyFileHeader + 48);
267 1 : sBFH.nBinaryGainRecovered = SEGYReadMSBInt16(abyFileHeader + 50);
268 1 : sBFH.nAmplitudeRecoveryMethod = SEGYReadMSBInt16(abyFileHeader + 52);
269 1 : sBFH.nMeasurementSystem = SEGYReadMSBInt16(abyFileHeader + 54);
270 1 : sBFH.nImpulseSignalPolarity = SEGYReadMSBInt16(abyFileHeader + 56);
271 1 : sBFH.nVibratoryPolaryCode = SEGYReadMSBInt16(abyFileHeader + 58);
272 1 : sBFH.nSEGYRevisionNumber = SEGYReadMSBInt16(abyFileHeader + 300) & 0xffff;
273 1 : sBFH.dfSEGYRevisionNumber = sBFH.nSEGYRevisionNumber / 256.0;
274 1 : sBFH.nFixedLengthTraceFlag = SEGYReadMSBInt16(abyFileHeader + 302);
275 1 : sBFH.nNumberOfExtendedTextualFileHeader = SEGYReadMSBInt16(abyFileHeader + 304);
276 :
277 : #if 0
278 : CPLDebug("SIGY", "nJobIdNumber = %d", sBFH.nJobIdNumber);
279 : CPLDebug("SIGY", "nLineNumber = %d", sBFH.nLineNumber);
280 : CPLDebug("SIGY", "nReelNumber = %d", sBFH.nReelNumber);
281 : CPLDebug("SIGY", "nDataTracesPerEnsemble = %d", sBFH.nDataTracesPerEnsemble);
282 : CPLDebug("SIGY", "nAuxTracesPerEnsemble = %d", sBFH.nAuxTracesPerEnsemble);
283 : CPLDebug("SIGY", "nSampleInterval = %d", sBFH.nSampleInterval);
284 : CPLDebug("SIGY", "nSampleIntervalOriginal = %d", sBFH.nSampleIntervalOriginal);
285 : CPLDebug("SIGY", "nSamplesPerDataTrace = %d", sBFH.nSamplesPerDataTrace);
286 : CPLDebug("SIGY", "nSamplesPerDataTraceOriginal = %d", sBFH.nSamplesPerDataTraceOriginal);
287 : CPLDebug("SIGY", "nDataSampleType = %d", sBFH.nDataSampleType);
288 : CPLDebug("SIGY", "nEnsembleFold = %d", sBFH.nEnsembleFold);
289 : CPLDebug("SIGY", "nTraceSortingCode = %d", sBFH.nTraceSortingCode);
290 : CPLDebug("SIGY", "nVerticalSumCode = %d", sBFH.nVerticalSumCode);
291 : CPLDebug("SIGY", "nSweepFrequencyAtStart = %d", sBFH.nSweepFrequencyAtStart);
292 : CPLDebug("SIGY", "nSweepFrequencyAtEnd = %d", sBFH.nSweepFrequencyAtEnd);
293 : CPLDebug("SIGY", "nSweepLength = %d", sBFH.nSweepLength);
294 : CPLDebug("SIGY", "nSweepType = %d", sBFH.nSweepType);
295 : CPLDebug("SIGY", "nTraceNumberOfSweepChannel = %d", sBFH.nTraceNumberOfSweepChannel);
296 : CPLDebug("SIGY", "nSweepTraceTaperLengthAtStart = %d", sBFH.nSweepTraceTaperLengthAtStart);
297 : CPLDebug("SIGY", "nSweepTraceTaperLengthAtEnd = %d", sBFH.nSweepTraceTaperLengthAtEnd);
298 : CPLDebug("SIGY", "nTaperType = %d", sBFH.nTaperType);
299 : CPLDebug("SIGY", "nCorrelated = %d", sBFH.nCorrelated);
300 : CPLDebug("SIGY", "nBinaryGainRecovered = %d", sBFH.nBinaryGainRecovered);
301 : CPLDebug("SIGY", "nAmplitudeRecoveryMethod = %d", sBFH.nAmplitudeRecoveryMethod);
302 : CPLDebug("SIGY", "nMeasurementSystem = %d", sBFH.nMeasurementSystem);
303 : CPLDebug("SIGY", "nImpulseSignalPolarity = %d", sBFH.nImpulseSignalPolarity);
304 : CPLDebug("SIGY", "nVibratoryPolaryCode = %d", sBFH.nVibratoryPolaryCode);
305 : CPLDebug("SIGY", "nSEGYRevisionNumber = %d", sBFH.nSEGYRevisionNumber);
306 : CPLDebug("SIGY", "dfSEGYRevisionNumber = %f", sBFH.dfSEGYRevisionNumber);
307 : CPLDebug("SIGY", "nFixedLengthTraceFlag = %d", sBFH.nFixedLengthTraceFlag);
308 : CPLDebug("SIGY", "nNumberOfExtendedTextualFileHeader = %d", sBFH.nNumberOfExtendedTextualFileHeader);
309 : #endif
310 :
311 : // --------------------------------------------------------------------
312 : // Create layer
313 : // --------------------------------------------------------------------
314 :
315 1 : nLayers = 2;
316 1 : papoLayers = (OGRLayer**) CPLMalloc(nLayers * sizeof(OGRLayer*));
317 1 : papoLayers[0] = new OGRSEGYLayer(pszName, fp, &sBFH);
318 2 : papoLayers[1] = new OGRSEGYHeaderLayer(CPLSPrintf("%s_header", CPLGetBasename(pszName)), &sBFH, (char*) pabyASCIITextHeader);
319 :
320 1 : return TRUE;
321 : }
|