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