1 : /******************************************************************************
2 : * $Id: rawdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
3 : *
4 : * Project: Generic Raw Binary Driver
5 : * Purpose: Implementation of RawDataset and RawRasterBand classes.
6 : * Author: Frank Warmerdam, warmerda@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
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, DAMAGES 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 "rawdataset.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: rawdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
35 :
36 : /************************************************************************/
37 : /* RawRasterBand() */
38 : /************************************************************************/
39 :
40 1100 : RawRasterBand::RawRasterBand( GDALDataset *poDS, int nBand,
41 : void * fpRaw, vsi_l_offset nImgOffset,
42 : int nPixelOffset, int nLineOffset,
43 : GDALDataType eDataType, int bNativeOrder,
44 1100 : int bIsVSIL, int bOwnsFP )
45 :
46 : {
47 1100 : this->poDS = poDS;
48 1100 : this->nBand = nBand;
49 1100 : this->eDataType = eDataType;
50 1100 : this->bIsVSIL = bIsVSIL;
51 1100 : this->bOwnsFP =bOwnsFP;
52 :
53 1100 : if (bIsVSIL)
54 : {
55 1074 : this->fpRaw = NULL;
56 1074 : this->fpRawL = (VSILFILE*) fpRaw;
57 : }
58 : else
59 : {
60 26 : this->fpRaw = (FILE*) fpRaw;
61 26 : this->fpRawL = NULL;
62 : }
63 1100 : this->nImgOffset = nImgOffset;
64 1100 : this->nPixelOffset = nPixelOffset;
65 1100 : this->nLineOffset = nLineOffset;
66 1100 : this->bNativeOrder = bNativeOrder;
67 :
68 : CPLDebug( "GDALRaw",
69 : "RawRasterBand(%p,%d,%p,\n"
70 : " Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
71 : poDS, nBand, fpRaw,
72 : (unsigned int) nImgOffset, nPixelOffset, nLineOffset,
73 1100 : GDALGetDataTypeName(eDataType), bNativeOrder );
74 :
75 : /* -------------------------------------------------------------------- */
76 : /* Treat one scanline as the block size. */
77 : /* -------------------------------------------------------------------- */
78 1100 : nBlockXSize = poDS->GetRasterXSize();
79 1100 : nBlockYSize = 1;
80 :
81 : /* -------------------------------------------------------------------- */
82 : /* Initialize other fields, and setup the line buffer. */
83 : /* -------------------------------------------------------------------- */
84 1100 : Initialize();
85 1100 : }
86 :
87 : /************************************************************************/
88 : /* RawRasterBand() */
89 : /************************************************************************/
90 :
91 33 : RawRasterBand::RawRasterBand( void * fpRaw, vsi_l_offset nImgOffset,
92 : int nPixelOffset, int nLineOffset,
93 : GDALDataType eDataType, int bNativeOrder,
94 33 : int nXSize, int nYSize, int bIsVSIL, int bOwnsFP )
95 :
96 : {
97 33 : this->poDS = NULL;
98 33 : this->nBand = 1;
99 33 : this->eDataType = eDataType;
100 33 : this->bIsVSIL = bIsVSIL;
101 33 : this->bOwnsFP =bOwnsFP;
102 :
103 33 : if (bIsVSIL)
104 : {
105 33 : this->fpRaw = NULL;
106 33 : this->fpRawL = (VSILFILE*) fpRaw;
107 : }
108 : else
109 : {
110 0 : this->fpRaw = (FILE*) fpRaw;
111 0 : this->fpRawL = NULL;
112 : }
113 33 : this->nImgOffset = nImgOffset;
114 33 : this->nPixelOffset = nPixelOffset;
115 33 : this->nLineOffset = nLineOffset;
116 33 : this->bNativeOrder = bNativeOrder;
117 :
118 :
119 : CPLDebug( "GDALRaw",
120 : "RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
121 : (unsigned int) nImgOffset, nPixelOffset, nLineOffset,
122 33 : GDALGetDataTypeName(eDataType), bNativeOrder );
123 :
124 : /* -------------------------------------------------------------------- */
125 : /* Treat one scanline as the block size. */
126 : /* -------------------------------------------------------------------- */
127 33 : nBlockXSize = nXSize;
128 33 : nBlockYSize = 1;
129 33 : nRasterXSize = nXSize;
130 33 : nRasterYSize = nYSize;
131 33 : if (!GDALCheckDatasetDimensions(nXSize, nYSize))
132 : {
133 0 : pLineBuffer = NULL;
134 0 : return;
135 : }
136 :
137 : /* -------------------------------------------------------------------- */
138 : /* Initialize other fields, and setup the line buffer. */
139 : /* -------------------------------------------------------------------- */
140 33 : Initialize();
141 0 : }
142 :
143 : /************************************************************************/
144 : /* Initialize() */
145 : /************************************************************************/
146 :
147 1133 : void RawRasterBand::Initialize()
148 :
149 : {
150 1133 : poCT = NULL;
151 1133 : eInterp = GCI_Undefined;
152 :
153 1133 : papszCategoryNames = NULL;
154 :
155 1133 : bDirty = FALSE;
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Allocate working scanline. */
159 : /* -------------------------------------------------------------------- */
160 1133 : nLoadedScanline = -1;
161 1133 : if (nBlockXSize <= 0 || nPixelOffset > INT_MAX / nBlockXSize)
162 : {
163 0 : nLineSize = 0;
164 0 : pLineBuffer = NULL;
165 : }
166 : else
167 : {
168 1133 : nLineSize = ABS(nPixelOffset) * nBlockXSize;
169 1133 : pLineBuffer = VSIMalloc2( ABS(nPixelOffset), nBlockXSize );
170 : }
171 1133 : if (pLineBuffer == NULL)
172 : {
173 : CPLError(CE_Failure, CPLE_AppDefined,
174 : "Could not allocate line buffer : nPixelOffset=%d, nBlockXSize=%d",
175 0 : nPixelOffset, nBlockXSize);
176 : }
177 :
178 1133 : if( nPixelOffset >= 0 )
179 1073 : pLineStart = pLineBuffer;
180 : else
181 60 : pLineStart = ((char *) pLineBuffer) + ABS(nPixelOffset) * (nBlockXSize-1);
182 1133 : }
183 :
184 : /************************************************************************/
185 : /* ~RawRasterBand() */
186 : /************************************************************************/
187 :
188 1133 : RawRasterBand::~RawRasterBand()
189 :
190 : {
191 1133 : if( poCT )
192 10 : delete poCT;
193 :
194 1133 : CSLDestroy( papszCategoryNames );
195 :
196 1133 : FlushCache();
197 :
198 1133 : if (bOwnsFP)
199 : {
200 56 : if ( bIsVSIL )
201 56 : VSIFCloseL( fpRawL );
202 : else
203 0 : VSIFClose( fpRaw );
204 : }
205 :
206 1133 : CPLFree( pLineBuffer );
207 1133 : }
208 :
209 :
210 : /************************************************************************/
211 : /* SetAccess() */
212 : /************************************************************************/
213 :
214 353 : void RawRasterBand::SetAccess( GDALAccess eAccess )
215 : {
216 353 : this->eAccess = eAccess;
217 353 : }
218 :
219 : /************************************************************************/
220 : /* FlushCache() */
221 : /* */
222 : /* We override this so we have the opportunity to call */
223 : /* fflush(). We don't want to do this all the time in the */
224 : /* write block function as it is kind of expensive. */
225 : /************************************************************************/
226 :
227 2273 : CPLErr RawRasterBand::FlushCache()
228 :
229 : {
230 : CPLErr eErr;
231 :
232 2273 : eErr = GDALRasterBand::FlushCache();
233 2273 : if( eErr != CE_None )
234 0 : return eErr;
235 :
236 : // If we have unflushed raw, flush it to disk now.
237 2273 : if ( bDirty )
238 : {
239 224 : if( bIsVSIL )
240 222 : VSIFFlushL( fpRawL );
241 : else
242 2 : VSIFFlush( fpRaw );
243 :
244 224 : bDirty = FALSE;
245 : }
246 :
247 2273 : return CE_None;
248 : }
249 :
250 : /************************************************************************/
251 : /* AccessLine() */
252 : /************************************************************************/
253 :
254 12554 : CPLErr RawRasterBand::AccessLine( int iLine )
255 :
256 : {
257 12554 : if (pLineBuffer == NULL)
258 0 : return CE_Failure;
259 :
260 12554 : if( nLoadedScanline == iLine )
261 0 : return CE_None;
262 :
263 : /* -------------------------------------------------------------------- */
264 : /* Figure out where to start reading. */
265 : /* -------------------------------------------------------------------- */
266 : vsi_l_offset nReadStart;
267 12554 : if( nPixelOffset >= 0 )
268 10721 : nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset;
269 : else
270 : {
271 : nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset
272 1833 : - ABS(nPixelOffset) * (nBlockXSize-1);
273 : }
274 :
275 : /* -------------------------------------------------------------------- */
276 : /* Seek to the right line. */
277 : /* -------------------------------------------------------------------- */
278 12554 : if( Seek(nReadStart, SEEK_SET) == -1 )
279 : {
280 0 : if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
281 : {
282 : CPLError( CE_Failure, CPLE_FileIO,
283 : "Failed to seek to scanline %d @ %d.\n",
284 0 : iLine, (int) (nImgOffset + (vsi_l_offset)iLine * nLineOffset) );
285 0 : return CE_Failure;
286 : }
287 : else
288 : {
289 0 : memset( pLineBuffer, 0, nPixelOffset * nBlockXSize );
290 0 : nLoadedScanline = iLine;
291 0 : return CE_None;
292 : }
293 : }
294 :
295 : /* -------------------------------------------------------------------- */
296 : /* Read the line. Take care not to request any more bytes than */
297 : /* are needed, and not to lose a partially successful scanline */
298 : /* read. */
299 : /* -------------------------------------------------------------------- */
300 : int nBytesToRead, nBytesActuallyRead;
301 :
302 : nBytesToRead = ABS(nPixelOffset) * (nBlockXSize - 1)
303 12554 : + GDALGetDataTypeSize(GetRasterDataType()) / 8;
304 :
305 12554 : nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
306 12554 : if( nBytesActuallyRead < nBlockXSize )
307 : {
308 648 : if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
309 : {
310 : CPLError( CE_Failure, CPLE_FileIO,
311 : "Failed to read scanline %d.\n",
312 1 : iLine);
313 1 : return CE_Failure;
314 : }
315 : else
316 : {
317 : memset( ((GByte *) pLineBuffer) + nBytesActuallyRead,
318 647 : 0, nBytesToRead - nBytesActuallyRead );
319 : }
320 : }
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Byte swap the interesting data, if required. */
324 : /* -------------------------------------------------------------------- */
325 12553 : if( !bNativeOrder && eDataType != GDT_Byte )
326 : {
327 2673 : if( GDALDataTypeIsComplex( eDataType ) )
328 : {
329 : int nWordSize;
330 :
331 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
332 0 : GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) );
333 : GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
334 0 : nWordSize, nBlockXSize, ABS(nPixelOffset) );
335 : }
336 : else
337 : GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
338 2673 : nBlockXSize, ABS(nPixelOffset) );
339 : }
340 :
341 12553 : nLoadedScanline = iLine;
342 :
343 12553 : return CE_None;
344 : }
345 :
346 : /************************************************************************/
347 : /* IReadBlock() */
348 : /************************************************************************/
349 :
350 9958 : CPLErr RawRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
351 : void * pImage )
352 :
353 : {
354 : CPLErr eErr;
355 :
356 9958 : CPLAssert( nBlockXOff == 0 );
357 :
358 9958 : if (pLineBuffer == NULL)
359 0 : return CE_Failure;
360 :
361 9958 : eErr = AccessLine( nBlockYOff );
362 :
363 : /* -------------------------------------------------------------------- */
364 : /* Copy data from disk buffer to user block buffer. */
365 : /* -------------------------------------------------------------------- */
366 : GDALCopyWords( pLineStart, eDataType, nPixelOffset,
367 : pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
368 9958 : nBlockXSize );
369 :
370 9958 : return eErr;
371 : }
372 :
373 : /************************************************************************/
374 : /* IWriteBlock() */
375 : /************************************************************************/
376 :
377 5649 : CPLErr RawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
378 : void * pImage )
379 :
380 : {
381 5649 : CPLErr eErr = CE_None;
382 :
383 5649 : CPLAssert( nBlockXOff == 0 );
384 :
385 5649 : if (pLineBuffer == NULL)
386 0 : return CE_Failure;
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* If the data for this band is completely contiguous we don't */
390 : /* have to worry about pre-reading from disk. */
391 : /* -------------------------------------------------------------------- */
392 5649 : if( ABS(nPixelOffset) > GDALGetDataTypeSize(eDataType) / 8 )
393 2596 : eErr = AccessLine( nBlockYOff );
394 :
395 : /* -------------------------------------------------------------------- */
396 : /* Copy data from user buffer into disk buffer. */
397 : /* -------------------------------------------------------------------- */
398 : GDALCopyWords( pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
399 : pLineStart, eDataType, nPixelOffset,
400 5649 : nBlockXSize );
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* Byte swap (if necessary) back into disk order before writing. */
404 : /* -------------------------------------------------------------------- */
405 5649 : if( !bNativeOrder && eDataType != GDT_Byte )
406 : {
407 169 : if( GDALDataTypeIsComplex( eDataType ) )
408 : {
409 : int nWordSize;
410 :
411 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
412 : GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
413 0 : ABS(nPixelOffset) );
414 : GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
415 0 : nWordSize, nBlockXSize, ABS(nPixelOffset) );
416 : }
417 : else
418 : GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
419 169 : nBlockXSize, ABS(nPixelOffset) );
420 : }
421 :
422 : /* -------------------------------------------------------------------- */
423 : /* Figure out where to start reading. */
424 : /* -------------------------------------------------------------------- */
425 : vsi_l_offset nWriteStart;
426 5649 : if( nPixelOffset >= 0 )
427 4944 : nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset;
428 : else
429 : {
430 : nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset
431 705 : - ABS(nPixelOffset) * (nBlockXSize-1);
432 : }
433 :
434 : /* -------------------------------------------------------------------- */
435 : /* Seek to correct location. */
436 : /* -------------------------------------------------------------------- */
437 5649 : if( Seek( nWriteStart, SEEK_SET ) == -1 )
438 : {
439 : CPLError( CE_Failure, CPLE_FileIO,
440 : "Failed to seek to scanline %d @ %d to write to file.\n",
441 0 : nBlockYOff, (int) (nImgOffset + nBlockYOff * nLineOffset) );
442 :
443 0 : eErr = CE_Failure;
444 : }
445 :
446 : /* -------------------------------------------------------------------- */
447 : /* Write data buffer. */
448 : /* -------------------------------------------------------------------- */
449 : int nBytesToWrite;
450 :
451 : nBytesToWrite = ABS(nPixelOffset) * (nBlockXSize - 1)
452 5649 : + GDALGetDataTypeSize(GetRasterDataType()) / 8;
453 :
454 5649 : if( eErr == CE_None
455 : && Write( pLineBuffer, 1, nBytesToWrite ) < (size_t) nBytesToWrite )
456 : {
457 : CPLError( CE_Failure, CPLE_FileIO,
458 : "Failed to write scanline %d to file.\n",
459 0 : nBlockYOff );
460 :
461 0 : eErr = CE_Failure;
462 : }
463 :
464 : /* -------------------------------------------------------------------- */
465 : /* Byte swap (if necessary) back into machine order so the */
466 : /* buffer is still usable for reading purposes. */
467 : /* -------------------------------------------------------------------- */
468 5649 : if( !bNativeOrder && eDataType != GDT_Byte )
469 : {
470 169 : if( GDALDataTypeIsComplex( eDataType ) )
471 : {
472 : int nWordSize;
473 :
474 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
475 : GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
476 0 : ABS(nPixelOffset) );
477 : GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
478 : nWordSize, nBlockXSize,
479 0 : ABS(nPixelOffset) );
480 : }
481 : else
482 : GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
483 169 : nBlockXSize, ABS(nPixelOffset) );
484 : }
485 :
486 5649 : bDirty = TRUE;
487 5649 : return eErr;
488 : }
489 :
490 : /************************************************************************/
491 : /* AccessBlock() */
492 : /************************************************************************/
493 :
494 0 : CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
495 : void * pData )
496 : {
497 : int nBytesActuallyRead;
498 :
499 : /* -------------------------------------------------------------------- */
500 : /* Seek to the right block. */
501 : /* -------------------------------------------------------------------- */
502 0 : if( Seek( nBlockOff, SEEK_SET ) == -1 )
503 : {
504 0 : memset( pData, 0, nBlockSize );
505 0 : return CE_None;
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Read the block. */
510 : /* -------------------------------------------------------------------- */
511 0 : nBytesActuallyRead = Read( pData, 1, nBlockSize );
512 0 : if( nBytesActuallyRead < nBlockSize )
513 : {
514 :
515 : memset( ((GByte *) pData) + nBytesActuallyRead,
516 0 : 0, nBlockSize - nBytesActuallyRead );
517 0 : return CE_None;
518 : }
519 :
520 : /* -------------------------------------------------------------------- */
521 : /* Byte swap the interesting data, if required. */
522 : /* -------------------------------------------------------------------- */
523 0 : if( !bNativeOrder && eDataType != GDT_Byte )
524 : {
525 0 : if( GDALDataTypeIsComplex( eDataType ) )
526 : {
527 : int nWordSize;
528 :
529 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
530 : GDALSwapWords( pData, nWordSize, nBlockSize / nPixelOffset,
531 0 : nPixelOffset );
532 : GDALSwapWords( ((GByte *) pData) + nWordSize,
533 0 : nWordSize, nBlockSize / nPixelOffset, nPixelOffset );
534 : }
535 : else
536 : GDALSwapWords( pData, GDALGetDataTypeSize(eDataType) / 8,
537 0 : nBlockSize / nPixelOffset, nPixelOffset );
538 : }
539 :
540 0 : return CE_None;
541 : }
542 :
543 : /************************************************************************/
544 : /* IsLineLoaded() */
545 : /* */
546 : /* Check whether at least one scanline from the specified block of */
547 : /* lines is cached. */
548 : /************************************************************************/
549 :
550 0 : int RawRasterBand::IsLineLoaded( int nLineOff, int nLines )
551 : {
552 : int iLine;
553 :
554 0 : for ( iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
555 : {
556 0 : GDALRasterBlock *poBlock = TryGetLockedBlockRef( 0, iLine );
557 0 : if( poBlock != NULL )
558 : {
559 0 : poBlock->DropLock();
560 0 : return TRUE;
561 : }
562 : }
563 :
564 0 : return FALSE;
565 : }
566 :
567 : /************************************************************************/
568 : /* IRasterIO() */
569 : /************************************************************************/
570 :
571 9198 : CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
572 : int nXOff, int nYOff, int nXSize, int nYSize,
573 : void * pData, int nBufXSize, int nBufYSize,
574 : GDALDataType eBufType,
575 : int nPixelSpace, int nLineSpace )
576 :
577 : {
578 9198 : int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
579 9198 : int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
580 9198 : int nBytesToRW = nPixelOffset * nXSize;
581 :
582 : /* -------------------------------------------------------------------- */
583 : /* Use direct IO without caching if: */
584 : /* */
585 : /* GDAL_ONE_BIG_READ is enabled */
586 : /* */
587 : /* or */
588 : /* */
589 : /* the length of a scanline on disk is more than 50000 bytes, and the */
590 : /* width of the requested chunk is less than 40% of the whole scanline */
591 : /* and none of the requested scanlines are already in the cache. */
592 : /* -------------------------------------------------------------------- */
593 9198 : if( nPixelOffset < 0 )
594 : {
595 : return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
596 : nXSize, nYSize,
597 : pData, nBufXSize, nBufYSize,
598 : eBufType,
599 715 : nPixelSpace, nLineSpace );
600 : }
601 :
602 8483 : if ( !CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
603 : {
604 8483 : if ( nLineSize < 50000
605 : || nBytesToRW > nLineSize / 5 * 2
606 : || IsLineLoaded( nYOff, nYSize ) )
607 : {
608 :
609 : return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
610 : nXSize, nYSize,
611 : pData, nBufXSize, nBufYSize,
612 : eBufType,
613 8483 : nPixelSpace, nLineSpace );
614 : }
615 : }
616 :
617 : /* ==================================================================== */
618 : /* Read data. */
619 : /* ==================================================================== */
620 0 : if ( eRWFlag == GF_Read )
621 : {
622 : /* -------------------------------------------------------------------- */
623 : /* Do we have overviews that would be appropriate to satisfy */
624 : /* this request? */
625 : /* -------------------------------------------------------------------- */
626 0 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
627 0 : && GetOverviewCount() > 0 )
628 : {
629 0 : if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
630 : pData, nBufXSize, nBufYSize,
631 : eBufType, nPixelSpace, nLineSpace ) == CE_None )
632 0 : return CE_None;
633 : }
634 :
635 : /* ==================================================================== */
636 : /* 1. Simplest case when we should get contiguous block */
637 : /* of uninterleaved pixels. */
638 : /* ==================================================================== */
639 0 : if ( nXSize == GetXSize()
640 : && nXSize == nBufXSize
641 : && nYSize == nBufYSize
642 : && eBufType == eDataType
643 : && nPixelOffset == nBandDataSize
644 : && nPixelSpace == nBufDataSize
645 : && nLineSpace == nPixelSpace * nXSize )
646 : {
647 0 : if ( AccessBlock( nImgOffset
648 : + (vsi_l_offset)nYOff * nLineOffset + nXOff,
649 : nXSize * nYSize * nBandDataSize, pData ) != CE_None )
650 : {
651 : CPLError( CE_Failure, CPLE_FileIO,
652 : "Failed to read %d bytes at %lu.",
653 : nXSize * nYSize * nBandDataSize,
654 : (unsigned long)
655 : (nImgOffset + (vsi_l_offset)nYOff * nLineOffset
656 0 : + nXOff) );
657 : }
658 : }
659 :
660 : /* ==================================================================== */
661 : /* 2. Case when we need deinterleave and/or subsample data. */
662 : /* ==================================================================== */
663 : else
664 : {
665 : GByte *pabyData;
666 : double dfSrcXInc, dfSrcYInc;
667 : int iLine;
668 :
669 0 : dfSrcXInc = (double)nXSize / nBufXSize;
670 0 : dfSrcYInc = (double)nYSize / nBufYSize;
671 :
672 :
673 0 : pabyData = (GByte *) CPLMalloc( nBytesToRW );
674 :
675 0 : for ( iLine = 0; iLine < nBufYSize; iLine++ )
676 : {
677 0 : if ( AccessBlock( nImgOffset
678 : + ((vsi_l_offset)nYOff
679 : + (int)(iLine * dfSrcYInc)) * nLineOffset
680 : + nXOff * nPixelOffset,
681 : nBytesToRW, pabyData ) != CE_None )
682 : {
683 : CPLError( CE_Failure, CPLE_FileIO,
684 : "Failed to read %d bytes at %lu.",
685 : nBytesToRW,
686 : (unsigned long)(nImgOffset
687 : + ((vsi_l_offset)nYOff
688 : + (int)(iLine * dfSrcYInc)) * nLineOffset
689 0 : + nXOff * nPixelOffset) );
690 : }
691 :
692 : /* -------------------------------------------------------------------- */
693 : /* Copy data from disk buffer to user block buffer and subsample, */
694 : /* if needed. */
695 : /* -------------------------------------------------------------------- */
696 0 : if ( nXSize == nBufXSize && nYSize == nBufYSize )
697 : {
698 : GDALCopyWords( pabyData, eDataType, nPixelOffset,
699 : (GByte *)pData + iLine * nLineSpace,
700 0 : eBufType, nPixelSpace, nXSize );
701 : }
702 : else
703 : {
704 : int iPixel;
705 :
706 0 : for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
707 : {
708 : GDALCopyWords( pabyData +
709 : (int)(iPixel * dfSrcXInc) * nPixelOffset,
710 : eDataType, 0,
711 : (GByte *)pData + iLine * nLineSpace +
712 : iPixel * nBufDataSize,
713 0 : eBufType, nPixelSpace, 1 );
714 : }
715 : }
716 : }
717 :
718 0 : CPLFree( pabyData );
719 : }
720 : }
721 :
722 : /* ==================================================================== */
723 : /* Write data. */
724 : /* ==================================================================== */
725 : else
726 : {
727 : int nBytesActuallyWritten;
728 :
729 : /* ==================================================================== */
730 : /* 1. Simplest case when we should write contiguous block */
731 : /* of uninterleaved pixels. */
732 : /* ==================================================================== */
733 0 : if ( nXSize == GetXSize()
734 : && nXSize == nBufXSize
735 : && nYSize == nBufYSize
736 : && eBufType == eDataType
737 : && nPixelOffset == nBandDataSize
738 : && nPixelSpace == nBufDataSize
739 : && nLineSpace == nPixelSpace * nXSize )
740 : {
741 : /* -------------------------------------------------------------------- */
742 : /* Byte swap the data buffer, if required. */
743 : /* -------------------------------------------------------------------- */
744 0 : if( !bNativeOrder && eDataType != GDT_Byte )
745 : {
746 0 : if( GDALDataTypeIsComplex( eDataType ) )
747 : {
748 : int nWordSize;
749 :
750 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
751 0 : GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
752 : GDALSwapWords( ((GByte *) pData) + nWordSize,
753 0 : nWordSize, nXSize, nPixelOffset );
754 : }
755 : else
756 0 : GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
757 : }
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Seek to the right block. */
761 : /* -------------------------------------------------------------------- */
762 0 : if( Seek( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff,
763 : SEEK_SET) == -1 )
764 : {
765 : CPLError( CE_Failure, CPLE_FileIO,
766 : "Failed to seek to %lu to write data.\n",
767 : (unsigned long)(nImgOffset + (vsi_l_offset)nYOff
768 0 : * nLineOffset + nXOff) );
769 :
770 0 : return CE_Failure;
771 : }
772 :
773 : /* -------------------------------------------------------------------- */
774 : /* Write the block. */
775 : /* -------------------------------------------------------------------- */
776 0 : nBytesToRW = nXSize * nYSize * nBandDataSize;
777 :
778 0 : nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
779 0 : if( nBytesActuallyWritten < nBytesToRW )
780 : {
781 : CPLError( CE_Failure, CPLE_FileIO,
782 : "Failed to write %d bytes to file. %d bytes written",
783 0 : nBytesToRW, nBytesActuallyWritten );
784 :
785 0 : return CE_Failure;
786 : }
787 :
788 : /* -------------------------------------------------------------------- */
789 : /* Byte swap (if necessary) back into machine order so the */
790 : /* buffer is still usable for reading purposes. */
791 : /* -------------------------------------------------------------------- */
792 0 : if( !bNativeOrder && eDataType != GDT_Byte )
793 : {
794 0 : if( GDALDataTypeIsComplex( eDataType ) )
795 : {
796 : int nWordSize;
797 :
798 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
799 0 : GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
800 : GDALSwapWords( ((GByte *) pData) + nWordSize,
801 0 : nWordSize, nXSize, nPixelOffset );
802 : }
803 : else
804 0 : GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
805 : }
806 : }
807 :
808 : /* ==================================================================== */
809 : /* 2. Case when we need deinterleave and/or subsample data. */
810 : /* ==================================================================== */
811 : else
812 : {
813 : GByte *pabyData;
814 : double dfSrcXInc, dfSrcYInc;
815 : vsi_l_offset nBlockOff;
816 : int iLine;
817 :
818 0 : dfSrcXInc = (double)nXSize / nBufXSize;
819 0 : dfSrcYInc = (double)nYSize / nBufYSize;
820 :
821 0 : pabyData = (GByte *) CPLMalloc( nBytesToRW );
822 :
823 0 : for ( iLine = 0; iLine < nBufYSize; iLine++ )
824 : {
825 : nBlockOff = nImgOffset
826 : + ((vsi_l_offset)nYOff + (int)(iLine*dfSrcYInc))*nLineOffset
827 0 : + nXOff * nPixelOffset;
828 :
829 : /* -------------------------------------------------------------------- */
830 : /* If the data for this band is completely contiguous we don't */
831 : /* have to worry about pre-reading from disk. */
832 : /* -------------------------------------------------------------------- */
833 0 : if( nPixelOffset > nBandDataSize )
834 0 : AccessBlock( nBlockOff, nBytesToRW, pabyData );
835 :
836 : /* -------------------------------------------------------------------- */
837 : /* Copy data from user block buffer to disk buffer and subsample, */
838 : /* if needed. */
839 : /* -------------------------------------------------------------------- */
840 0 : if ( nXSize == nBufXSize && nYSize == nBufYSize )
841 : {
842 : GDALCopyWords( (GByte *)pData + iLine * nLineSpace,
843 : eBufType, nPixelSpace,
844 0 : pabyData, eDataType, nPixelOffset, nXSize );
845 : }
846 : else
847 : {
848 : int iPixel;
849 :
850 0 : for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
851 : {
852 : GDALCopyWords( (GByte *)pData+iLine*nLineSpace +
853 : iPixel * nBufDataSize,
854 : eBufType, nPixelSpace,
855 : pabyData +
856 : (int)(iPixel * dfSrcXInc) * nPixelOffset,
857 0 : eDataType, 0, 1 );
858 : }
859 : }
860 :
861 : /* -------------------------------------------------------------------- */
862 : /* Byte swap the data buffer, if required. */
863 : /* -------------------------------------------------------------------- */
864 0 : if( !bNativeOrder && eDataType != GDT_Byte )
865 : {
866 0 : if( GDALDataTypeIsComplex( eDataType ) )
867 : {
868 : int nWordSize;
869 :
870 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
871 0 : GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
872 : GDALSwapWords( ((GByte *) pabyData) + nWordSize,
873 0 : nWordSize, nXSize, nPixelOffset );
874 : }
875 : else
876 : GDALSwapWords( pabyData, nBandDataSize, nXSize,
877 0 : nPixelOffset );
878 : }
879 :
880 : /* -------------------------------------------------------------------- */
881 : /* Seek to the right line in block. */
882 : /* -------------------------------------------------------------------- */
883 0 : if( Seek( nBlockOff, SEEK_SET) == -1 )
884 : {
885 : CPLError( CE_Failure, CPLE_FileIO,
886 : "Failed to seek to %ld to read.\n",
887 0 : (long)nBlockOff );
888 :
889 0 : return CE_Failure;
890 : }
891 :
892 : /* -------------------------------------------------------------------- */
893 : /* Write the line of block. */
894 : /* -------------------------------------------------------------------- */
895 0 : nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW );
896 0 : if( nBytesActuallyWritten < nBytesToRW )
897 : {
898 : CPLError( CE_Failure, CPLE_FileIO,
899 : "Failed to write %d bytes to file. %d bytes written",
900 0 : nBytesToRW, nBytesActuallyWritten );
901 :
902 0 : return CE_Failure;
903 : }
904 :
905 : /* -------------------------------------------------------------------- */
906 : /* Byte swap (if necessary) back into machine order so the */
907 : /* buffer is still usable for reading purposes. */
908 : /* -------------------------------------------------------------------- */
909 0 : if( !bNativeOrder && eDataType != GDT_Byte )
910 : {
911 0 : if( GDALDataTypeIsComplex( eDataType ) )
912 : {
913 : int nWordSize;
914 :
915 0 : nWordSize = GDALGetDataTypeSize(eDataType)/16;
916 0 : GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
917 : GDALSwapWords( ((GByte *) pabyData) + nWordSize,
918 0 : nWordSize, nXSize, nPixelOffset );
919 : }
920 : else
921 : GDALSwapWords( pabyData, nBandDataSize, nXSize,
922 0 : nPixelOffset );
923 : }
924 :
925 : }
926 :
927 0 : bDirty = TRUE;
928 0 : CPLFree( pabyData );
929 : }
930 : }
931 :
932 0 : return CE_None;
933 : }
934 :
935 : /************************************************************************/
936 : /* Seek() */
937 : /************************************************************************/
938 :
939 18203 : int RawRasterBand::Seek( vsi_l_offset nOffset, int nSeekMode )
940 :
941 : {
942 18203 : if( bIsVSIL )
943 17024 : return VSIFSeekL( fpRawL, nOffset, nSeekMode );
944 : else
945 1179 : return VSIFSeek( fpRaw, (long) nOffset, nSeekMode );
946 : }
947 :
948 : /************************************************************************/
949 : /* Read() */
950 : /************************************************************************/
951 :
952 12554 : size_t RawRasterBand::Read( void *pBuffer, size_t nSize, size_t nCount )
953 :
954 : {
955 12554 : if( bIsVSIL )
956 11677 : return VSIFReadL( pBuffer, nSize, nCount, fpRawL );
957 : else
958 877 : return VSIFRead( pBuffer, nSize, nCount, fpRaw );
959 : }
960 :
961 : /************************************************************************/
962 : /* Write() */
963 : /************************************************************************/
964 :
965 5649 : size_t RawRasterBand::Write( void *pBuffer, size_t nSize, size_t nCount )
966 :
967 : {
968 5649 : if( bIsVSIL )
969 5347 : return VSIFWriteL( pBuffer, nSize, nCount, fpRawL );
970 : else
971 302 : return VSIFWrite( pBuffer, nSize, nCount, fpRaw );
972 : }
973 :
974 : /************************************************************************/
975 : /* StoreNoDataValue() */
976 : /* */
977 : /* This is a helper function for datasets to associate a no */
978 : /* data value with this band, it isn't intended to be called by */
979 : /* applications. */
980 : /************************************************************************/
981 :
982 0 : void RawRasterBand::StoreNoDataValue( double dfValue )
983 :
984 : {
985 0 : SetNoDataValue( dfValue );
986 0 : }
987 :
988 : /************************************************************************/
989 : /* GetCategoryNames() */
990 : /************************************************************************/
991 :
992 212 : char **RawRasterBand::GetCategoryNames()
993 :
994 : {
995 212 : return papszCategoryNames;
996 : }
997 :
998 : /************************************************************************/
999 : /* SetCategoryNames() */
1000 : /************************************************************************/
1001 :
1002 4 : CPLErr RawRasterBand::SetCategoryNames( char ** papszNewNames )
1003 :
1004 : {
1005 4 : CSLDestroy( papszCategoryNames );
1006 4 : papszCategoryNames = CSLDuplicate( papszNewNames );
1007 :
1008 4 : return CE_None;
1009 : }
1010 :
1011 : /************************************************************************/
1012 : /* SetColorTable() */
1013 : /************************************************************************/
1014 :
1015 10 : CPLErr RawRasterBand::SetColorTable( GDALColorTable *poNewCT )
1016 :
1017 : {
1018 10 : if( poCT )
1019 0 : delete poCT;
1020 10 : if( poNewCT == NULL )
1021 0 : poCT = NULL;
1022 : else
1023 10 : poCT = poNewCT->Clone();
1024 :
1025 10 : return CE_None;
1026 : }
1027 :
1028 : /************************************************************************/
1029 : /* GetColorTable() */
1030 : /************************************************************************/
1031 :
1032 63 : GDALColorTable *RawRasterBand::GetColorTable()
1033 :
1034 : {
1035 63 : return poCT;
1036 : }
1037 :
1038 : /************************************************************************/
1039 : /* SetColorInterpretation() */
1040 : /************************************************************************/
1041 :
1042 194 : CPLErr RawRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
1043 :
1044 : {
1045 194 : eInterp = eNewInterp;
1046 :
1047 194 : return CE_None;
1048 : }
1049 :
1050 : /************************************************************************/
1051 : /* GetColorInterpretation() */
1052 : /************************************************************************/
1053 :
1054 169 : GDALColorInterp RawRasterBand::GetColorInterpretation()
1055 :
1056 : {
1057 169 : return eInterp;
1058 : }
1059 :
1060 : /************************************************************************/
1061 : /* ==================================================================== */
1062 : /* RawDataset */
1063 : /* ==================================================================== */
1064 : /************************************************************************/
1065 :
1066 :
1067 : /************************************************************************/
1068 : /* RawDataset() */
1069 : /************************************************************************/
1070 :
1071 604 : RawDataset::RawDataset()
1072 :
1073 : {
1074 604 : }
1075 :
1076 : /************************************************************************/
1077 : /* ~RawDataset() */
1078 : /************************************************************************/
1079 :
1080 604 : RawDataset::~RawDataset()
1081 :
1082 : {
1083 : /* It's pure virtual function but must be defined, even if empty. */
1084 604 : }
1085 :
1086 : /************************************************************************/
1087 : /* IRasterIO() */
1088 : /* */
1089 : /* Multi-band raster io handler. */
1090 : /************************************************************************/
1091 :
1092 228 : CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
1093 : int nXOff, int nYOff, int nXSize, int nYSize,
1094 : void *pData, int nBufXSize, int nBufYSize,
1095 : GDALDataType eBufType,
1096 : int nBandCount, int *panBandMap,
1097 : int nPixelSpace, int nLineSpace, int nBandSpace )
1098 :
1099 : {
1100 : /* if( nBandCount > 1 )
1101 : return GDALDataset::BlockBasedRasterIO(
1102 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
1103 : pData, nBufXSize, nBufYSize, eBufType,
1104 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
1105 : else*/
1106 : return
1107 : GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1108 : pData, nBufXSize, nBufYSize, eBufType,
1109 : nBandCount, panBandMap,
1110 228 : nPixelSpace, nLineSpace, nBandSpace );
1111 : }
1112 :
1113 :
|