Line data Source code
1 : /******************************************************************************
2 : *
3 : * Purpose: Block directory API.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2011
7 : * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "blockdir/blocktilelayer.h"
29 : #include "blockdir/blockdir.h"
30 : #include "blockdir/blockfile.h"
31 : #include "blockdir/asciitiledir.h"
32 : #include "blockdir/binarytiledir.h"
33 : #include "core/mutexholder.h"
34 : #include "pcidsk_types.h"
35 : #include "pcidsk_exception.h"
36 : #include <cstdlib>
37 : #include <cstring>
38 : #include <cassert>
39 : #include <algorithm>
40 : #include <limits>
41 :
42 : #ifdef PCIMAJORVERSION
43 : #include "raster/memcmp.hh"
44 : #include "raster/memset.hh"
45 : #endif
46 :
47 : namespace PCIDSK
48 : {
49 :
50 : /************************************************************************/
51 : /* BlockTileLayer() */
52 : /************************************************************************/
53 :
54 : /**
55 : * Constructor.
56 : *
57 : * @param poBlockDir The associated block directory.
58 : * @param nLayer The index of the block layer.
59 : * @param psBlockLayer The block layer info.
60 : * @param psTileLayer The tile layer info.
61 : */
62 49 : BlockTileLayer::BlockTileLayer(BlockDir * poBlockDir, uint32 nLayer,
63 : BlockLayerInfo * psBlockLayer,
64 49 : TileLayerInfo * psTileLayer)
65 : : BlockLayer(poBlockDir, nLayer),
66 : mpsBlockLayer(psBlockLayer),
67 : mpsTileLayer(psTileLayer),
68 49 : mbModified(false)
69 : {
70 49 : memset(mszDataType, 0, sizeof(mszDataType));
71 49 : memset(mszCompress, 0, sizeof(mszCompress));
72 :
73 49 : mpoTileListMutex = DefaultCreateMutex();
74 49 : }
75 :
76 : /************************************************************************/
77 : /* ~BlockTileLayer() */
78 : /************************************************************************/
79 :
80 : /**
81 : * Destructor.
82 : */
83 49 : BlockTileLayer::~BlockTileLayer(void)
84 : {
85 49 : delete mpoTileListMutex;
86 49 : }
87 :
88 : /************************************************************************/
89 : /* GetTileInfo() */
90 : /************************************************************************/
91 :
92 : /**
93 : * Gets the tile at the specified index.
94 : *
95 : * @param nCol The column of the tile.
96 : * @param nRow The row of the tile.
97 : *
98 : * @return The tile at the specified index.
99 : */
100 : BlockTileLayer::BlockTileInfo *
101 70 : BlockTileLayer::GetTileInfo(uint32 nCol, uint32 nRow)
102 : {
103 70 : if (!IsValid())
104 0 : return nullptr;
105 :
106 70 : uint32 nTilesPerRow = GetTilePerRow();
107 :
108 70 : uint32 iTile = nRow * nTilesPerRow + nCol;
109 :
110 70 : MutexHolder oLock(mpoTileListMutex);
111 :
112 70 : if (moTileList.empty())
113 12 : ReadTileList();
114 :
115 70 : return &moTileList.at(iTile);
116 : }
117 :
118 : /************************************************************************/
119 : /* Sync() */
120 : /************************************************************************/
121 :
122 : /**
123 : * Synchronizes the block tile layer to disk.
124 : */
125 50 : void BlockTileLayer::Sync(void)
126 : {
127 50 : if (!mbModified)
128 42 : return;
129 :
130 : try
131 : {
132 8 : if (!GetFile()->GetUpdatable())
133 0 : return;
134 : }
135 0 : catch (...)
136 : {
137 0 : return;
138 : }
139 :
140 8 : MutexHolder oLock(mpoTileListMutex);
141 :
142 8 : if (!mbModified)
143 0 : return;
144 :
145 8 : WriteTileList();
146 :
147 8 : mbModified = false;
148 : }
149 :
150 : /************************************************************************/
151 : /* IsCorrupted() */
152 : /************************************************************************/
153 28 : bool BlockTileLayer::IsCorrupted(void) const
154 : {
155 : // Dead layers have a tile size of 0, but it should be considered valid.
156 28 : if (GetLayerType() == BLTDead)
157 0 : return false;
158 :
159 : // The tile layer is corrupted when the image size is 0.
160 28 : if (GetXSize() == 0 || GetYSize() == 0)
161 0 : return true;
162 :
163 : uint64 nTileSize =
164 28 : static_cast<uint64>(GetTileXSize()) * GetTileYSize() * GetDataTypeSize();
165 :
166 28 : return nTileSize == 0 || nTileSize > std::numeric_limits<uint32>::max();
167 : }
168 :
169 : /************************************************************************/
170 : /* GetTileCount() */
171 : /************************************************************************/
172 :
173 : /**
174 : * Gets the number of tiles in the tile layer.
175 : *
176 : * @return The number of tiles in the tile layer.
177 : */
178 61 : uint32 BlockTileLayer::GetTileCount(void) const
179 : {
180 61 : return (uint32) (((static_cast<uint64>(GetXSize()) + GetTileXSize() - 1) / GetTileXSize()) *
181 61 : ((static_cast<uint64>(GetYSize()) + GetTileYSize() - 1) / GetTileYSize()));
182 : }
183 :
184 : /************************************************************************/
185 : /* GetTilePerRow() */
186 : /************************************************************************/
187 :
188 : /**
189 : * Gets the number of tiles per row in the tile layer.
190 : *
191 : * @return The number of tiles per row in the tile layer.
192 : */
193 107 : uint32 BlockTileLayer::GetTilePerRow(void) const
194 : {
195 107 : return (uint32) (static_cast<uint64>(GetXSize()) + GetTileXSize() - 1) / GetTileXSize();
196 : }
197 :
198 : /************************************************************************/
199 : /* GetTilePerCol() */
200 : /************************************************************************/
201 :
202 : /**
203 : * Gets the number of tiles per column in the tile layer.
204 : *
205 : * @return The number of tiles per column in the tile layer.
206 : */
207 0 : uint32 BlockTileLayer::GetTilePerCol(void) const
208 : {
209 0 : return (uint32) (static_cast<uint64>(GetYSize()) + GetTileYSize() - 1) / GetTileYSize();
210 : }
211 :
212 : /************************************************************************/
213 : /* GetTileSize() */
214 : /************************************************************************/
215 :
216 : /**
217 : * Gets the size in bytes of a tile.
218 : *
219 : * @return The size in bytes of a tile.
220 : */
221 45 : uint32 BlockTileLayer::GetTileSize(void) const
222 : {
223 45 : return GetTileXSize() * GetTileYSize() * GetDataTypeSize();
224 : }
225 :
226 : /************************************************************************/
227 : /* GetDataTypeSize() */
228 : /************************************************************************/
229 :
230 : /**
231 : * Gets the data type size in bytes.
232 : *
233 : * @return The data type size in bytes.
234 : */
235 73 : uint32 BlockTileLayer::GetDataTypeSize(void) const
236 : {
237 73 : return DataTypeSize(GetDataTypeFromName(GetDataType()));
238 : }
239 :
240 : /************************************************************************/
241 : /* IsTileValid() */
242 : /************************************************************************/
243 :
244 : /**
245 : * Checks if the specified tile is valid.
246 : *
247 : * @param nCol The column of the tile.
248 : * @param nRow The row of the tile.
249 : *
250 : * @return If the specified tile is valid.
251 : */
252 0 : bool BlockTileLayer::IsTileValid(uint32 nCol, uint32 nRow)
253 : {
254 0 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
255 :
256 0 : return (psTile && psTile->nOffset != INVALID_OFFSET && psTile->nSize != 0 &&
257 0 : AreBlocksAllocated(psTile->nOffset, psTile->nSize));
258 : }
259 :
260 : /************************************************************************/
261 : /* GetTileDataSize() */
262 : /************************************************************************/
263 :
264 : /**
265 : * Gets the size in bytes of the specified tile.
266 : *
267 : * @param nCol The column of the tile.
268 : * @param nRow The row of the tile.
269 : *
270 : * @return The size in bytes of the specified tile.
271 : */
272 4 : uint32 BlockTileLayer::GetTileDataSize(uint32 nCol, uint32 nRow)
273 : {
274 4 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
275 :
276 4 : return psTile ? psTile->nSize : 0;
277 : }
278 :
279 : /************************************************************************/
280 : /* WriteSparseTile() */
281 : /************************************************************************/
282 :
283 : /**
284 : * Writes the specified tile only if the data is sparse.
285 : *
286 : * @param pData The data of the tile.
287 : * @param nCol The column of the tile.
288 : * @param nRow The row of the tile.
289 : *
290 : * @return If the specified tile data is sparse.
291 : */
292 8 : bool BlockTileLayer::WriteSparseTile(const void * pData,
293 : uint32 nCol, uint32 nRow)
294 : {
295 8 : MutexHolder oLock(mpoTileListMutex);
296 :
297 8 : uint32 nValue = 0;
298 :
299 8 : bool bIsSparse = true;
300 :
301 8 : uint32 nTileSize = GetTileSize();
302 :
303 : // Check if we can use a sparse tile with a 4 byte value.
304 8 : if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
305 : {
306 6 : uint32 * pnIter = (uint32 *) pData;
307 :
308 6 : nValue = *pnIter;
309 :
310 : #ifdef PCIMAJORVERSION
311 : bIsSparse = raster::memcmp32(pnIter, nValue,
312 : nTileSize / sizeof(uint32));
313 : #else
314 6 : uint32 * pnEnd = pnIter + nTileSize / sizeof(uint32);
315 364 : for (; pnIter < pnEnd; ++pnIter)
316 : {
317 364 : if (*pnIter != nValue)
318 : {
319 6 : bIsSparse = false;
320 6 : break;
321 : }
322 : }
323 : #endif
324 : }
325 : // Check if we can use a sparse tile with a value of 0.
326 : else
327 : {
328 2 : nValue = 0;
329 :
330 : #ifdef PCIMAJORVERSION
331 : bIsSparse = raster::memcmp8((uchar *) pData, 0, nTileSize);
332 : #else
333 2 : uchar * pnIter = (uchar *) pData;
334 2 : uchar * pnEnd = pnIter + nTileSize;
335 718 : for (; pnIter < pnEnd; ++pnIter)
336 : {
337 718 : if (*pnIter != nValue)
338 : {
339 2 : bIsSparse = false;
340 2 : break;
341 : }
342 : }
343 : #endif
344 : }
345 :
346 : // If the tile data is sparse store the sparse value in the nSize member
347 : // of the BlockTileInfo structure.
348 8 : if (bIsSparse)
349 : {
350 0 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
351 0 : if( psTile != nullptr ) // TODO: what if it is null
352 : {
353 : // Free the blocks used by the tile.
354 0 : if (psTile->nOffset != INVALID_OFFSET)
355 0 : FreeBlocks(psTile->nOffset, psTile->nSize);
356 :
357 0 : psTile->nOffset = INVALID_OFFSET;
358 :
359 0 : psTile->nSize = nValue;
360 :
361 0 : mbModified = true;
362 : }
363 : }
364 :
365 16 : return bIsSparse;
366 : }
367 :
368 : /************************************************************************/
369 : /* WriteTile() */
370 : /************************************************************************/
371 :
372 : /**
373 : * Writes the specified tile.
374 : *
375 : * @param pData The data of the tile.
376 : * @param nCol The column of the tile.
377 : * @param nRow The row of the tile.
378 : * @param nSize The size of the tile.
379 : */
380 8 : void BlockTileLayer::WriteTile(const void * pData,
381 : uint32 nCol, uint32 nRow, uint32 nSize)
382 : {
383 8 : MutexHolder oLock(mpoTileListMutex);
384 :
385 8 : if (!IsValid())
386 0 : return;
387 :
388 8 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
389 :
390 8 : if (!psTile)
391 0 : return;
392 :
393 8 : if (nSize == 0)
394 4 : nSize = GetTileSize();
395 :
396 8 : if (psTile->nOffset == INVALID_OFFSET)
397 : {
398 8 : psTile->nOffset = GetLayerSize();
399 :
400 8 : psTile->nSize = nSize;
401 :
402 8 : mbModified = true;
403 : }
404 :
405 8 : if (psTile->nSize < nSize)
406 : {
407 0 : psTile->nOffset = GetLayerSize();
408 :
409 0 : psTile->nSize = nSize;
410 :
411 0 : mbModified = true;
412 : }
413 8 : else if (psTile->nSize > nSize)
414 : {
415 0 : psTile->nSize = nSize;
416 :
417 0 : mbModified = true;
418 : }
419 :
420 8 : WriteToLayer(pData, psTile->nOffset, psTile->nSize);
421 : }
422 :
423 : /************************************************************************/
424 : /* ReadSparseTile() */
425 : /************************************************************************/
426 :
427 : /**
428 : * Reads the specified tile only if the data is sparse.
429 : *
430 : * @param pData The data of the tile.
431 : * @param nCol The column of the tile.
432 : * @param nRow The row of the tile.
433 : *
434 : * @return If the specified tile data is sparse.
435 : */
436 29 : bool BlockTileLayer::ReadSparseTile(void * pData, uint32 nCol, uint32 nRow)
437 : {
438 29 : if (!IsValid())
439 0 : return false;
440 :
441 29 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
442 :
443 29 : if (!psTile)
444 0 : return false;
445 :
446 29 : if (psTile->nOffset != INVALID_OFFSET)
447 29 : return false;
448 :
449 0 : uint32 nTileSize = GetTileSize();
450 :
451 : // Check if we can use a sparse tile with a 4 byte value.
452 0 : if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
453 : {
454 : #ifdef PCIMAJORVERSION
455 : raster::memset32((uint32 *) pData, psTile->nSize,
456 : nTileSize / sizeof(uint32));
457 : #else
458 0 : uint32 * pnIter = (uint32 *) pData;
459 0 : uint32 * pnEnd = pnIter + nTileSize / sizeof(uint32);
460 0 : for (; pnIter < pnEnd; ++pnIter)
461 0 : *pnIter = psTile->nSize;
462 : #endif
463 : }
464 : // Check if we can use a sparse tile with a value of 0.
465 : else
466 : {
467 0 : memset(pData, 0, nTileSize);
468 : }
469 :
470 0 : return true;
471 : }
472 :
473 : /************************************************************************/
474 : /* ReadTile() */
475 : /************************************************************************/
476 :
477 : /**
478 : * Reads the specified tile.
479 : *
480 : * @param pData The data of the tile.
481 : * @param nCol The column of the tile.
482 : * @param nRow The row of the tile.
483 : * @param nSize The buffer size.
484 : *
485 : * @return The size of the tile.
486 : */
487 29 : uint32 BlockTileLayer::ReadTile(void * pData, uint32 nCol, uint32 nRow, uint32 nSize)
488 : {
489 29 : if (!IsValid())
490 0 : return 0;
491 :
492 29 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
493 :
494 29 : if (!psTile)
495 0 : return 0;
496 :
497 29 : if (psTile->nOffset == INVALID_OFFSET)
498 0 : return 0;
499 :
500 29 : if (psTile->nSize == 0)
501 0 : return 0;
502 :
503 29 : uint32 nReadSize = std::min(nSize, psTile->nSize);
504 :
505 : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
506 29 : assert(psTile->nSize == nSize);
507 : #endif
508 :
509 29 : if (!ReadFromLayer(pData, psTile->nOffset, nReadSize))
510 0 : return 0;
511 :
512 29 : return nReadSize;
513 : }
514 :
515 : /************************************************************************/
516 : /* ReadPartialSparseTile() */
517 : /************************************************************************/
518 :
519 : /**
520 : * Reads the specified tile only if the data is sparse.
521 : *
522 : * @param pData The data of the tile.
523 : * @param nCol The column of the tile.
524 : * @param nRow The row of the tile.
525 : * @param nOffset The offset of the data.
526 : * @param nSize The size of the data.
527 : *
528 : * @return If the specified tile data is sparse.
529 : */
530 0 : bool BlockTileLayer::ReadPartialSparseTile(void * pData,
531 : uint32 nCol, uint32 nRow,
532 : uint32 nOffset, uint32 nSize)
533 : {
534 0 : if (!IsValid())
535 0 : return false;
536 :
537 0 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
538 :
539 0 : if (!psTile)
540 0 : return false;
541 :
542 0 : if (psTile->nOffset != INVALID_OFFSET)
543 0 : return false;
544 :
545 0 : uint32 nTileSize = GetTileSize();
546 :
547 : // Check if we can use a sparse tile with a 4 byte value.
548 0 : if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
549 : {
550 0 : uint32 nValue = psTile->nSize;
551 :
552 : // We need to bitwise shift the value if the offset isn't aligned.
553 0 : uint32 nByteOffset = nOffset % 4;
554 :
555 0 : if (nByteOffset != 0)
556 : {
557 0 : uint32 nBitOffset = nByteOffset * 8;
558 :
559 0 : nValue = (nValue << nBitOffset) | (nValue >> (32 - nBitOffset));
560 : }
561 :
562 0 : uint32 nAlign = nSize / sizeof(uint32);
563 :
564 : #ifdef PCIMAJORVERSION
565 : raster::memset32((uint32 *) pData, nValue, nAlign);
566 : #else
567 0 : uint32 * pnIter = (uint32 *) pData;
568 0 : uint32 * pnEnd = pnIter + nAlign;
569 0 : for (; pnIter < pnEnd; ++pnIter)
570 0 : *pnIter = nValue;
571 : #endif
572 :
573 0 : uint32 nRemaining = nSize % 4;
574 :
575 0 : if (nRemaining != 0)
576 : {
577 0 : uchar * pbyIter = (uchar *) pData + nAlign * 4;
578 :
579 0 : do
580 : {
581 0 : nValue = (nValue << 8) | (nValue >> 24);
582 :
583 0 : *pbyIter++ = (uchar) nValue;
584 : }
585 0 : while (--nRemaining);
586 : }
587 : }
588 : // Check if we can use a sparse tile with a value of 0.
589 : else
590 : {
591 0 : memset(pData, 0, nSize);
592 : }
593 :
594 0 : return true;
595 : }
596 :
597 : /************************************************************************/
598 : /* ReadPartialTile() */
599 : /************************************************************************/
600 :
601 : /**
602 : * Reads the specified tile.
603 : *
604 : * @param pData The data of the tile.
605 : * @param nCol The column of the tile.
606 : * @param nRow The row of the tile.
607 : * @param nOffset The offset of the data.
608 : * @param nSize The size of the data.
609 : *
610 : * @return If the read was successful.
611 : */
612 0 : bool BlockTileLayer::ReadPartialTile(void * pData, uint32 nCol, uint32 nRow,
613 : uint32 nOffset, uint32 nSize)
614 : {
615 0 : if (!IsValid())
616 0 : return false;
617 :
618 0 : BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
619 :
620 0 : if (!psTile)
621 0 : return false;
622 :
623 0 : if (psTile->nOffset == INVALID_OFFSET)
624 0 : return false;
625 :
626 0 : if (psTile->nSize == 0 || psTile->nSize < nOffset + nSize)
627 0 : return false;
628 :
629 0 : if (!ReadFromLayer(pData, psTile->nOffset + nOffset, nSize))
630 0 : return false;
631 :
632 0 : return true;
633 : }
634 :
635 : /************************************************************************/
636 : /* SetTileLayerInfo() */
637 : /************************************************************************/
638 :
639 : /**
640 : * Sets the tile layer information.
641 : *
642 : * @param nXSize The width of the tile layer.
643 : * @param nYSize The height of the tile layer.
644 : * @param nTileXSize The width of a tile.
645 : * @param nTileYSize The height of a tile.
646 : * @param oDataType The data type of the tile layer.
647 : * @param oCompress The compress type of the tile layer.
648 : * @param bNoDataValid If the NoData value is valid.
649 : * @param dfNoDataValue The NoData value of the tile layer.
650 : */
651 8 : void BlockTileLayer::SetTileLayerInfo(uint32 nXSize, uint32 nYSize,
652 : uint32 nTileXSize, uint32 nTileYSize,
653 : const std::string & oDataType,
654 : const std::string & oCompress,
655 : bool bNoDataValid, double dfNoDataValue)
656 : {
657 : uint64 nTileSize =
658 8 : static_cast<uint64>(nTileXSize) * nTileYSize *
659 8 : DataTypeSize(GetDataTypeFromName(oDataType.c_str()));
660 :
661 8 : if (nTileSize == 0 || nTileSize > std::numeric_limits<uint32>::max())
662 : {
663 0 : return ThrowPCIDSKException("Invalid tile dimensions: %d x %d",
664 0 : nTileXSize, nTileYSize);
665 : }
666 :
667 8 : if (nXSize == 0 || nYSize == 0)
668 : {
669 0 : return ThrowPCIDSKException("Invalid tile layer dimensions: %d x %d",
670 0 : nXSize, nYSize);
671 : }
672 :
673 8 : mpsTileLayer->nXSize = nXSize;
674 8 : mpsTileLayer->nYSize = nYSize;
675 8 : mpsTileLayer->nTileXSize = nTileXSize;
676 8 : mpsTileLayer->nTileYSize = nTileYSize;
677 8 : mpsTileLayer->bNoDataValid = bNoDataValid;
678 8 : mpsTileLayer->dfNoDataValue = dfNoDataValue;
679 :
680 8 : memset(mpsTileLayer->szDataType, ' ', 4);
681 8 : memcpy(mpsTileLayer->szDataType, oDataType.data(), oDataType.size());
682 :
683 8 : memset(mpsTileLayer->szCompress, ' ', 8);
684 8 : memcpy(mpsTileLayer->szCompress, oCompress.data(), oCompress.size());
685 :
686 : // Invalidate the cache variables.
687 8 : *mszDataType = 0;
688 8 : *mszCompress = 0;
689 :
690 : // Initialize the tile list.
691 8 : uint32 nTileCount = GetTileCount();
692 :
693 8 : MutexHolder oLock(mpoTileListMutex);
694 :
695 : try
696 : {
697 8 : moTileList.resize(nTileCount);
698 : }
699 0 : catch (const std::exception & ex)
700 : {
701 0 : return ThrowPCIDSKException("Out of memory in BlockTileLayer::SetTileLayerInfo(): %s", ex.what());
702 : }
703 :
704 16 : for (uint32 iTile = 0; iTile < nTileCount; iTile++)
705 : {
706 8 : BlockTileInfo * psTile = &moTileList[iTile];
707 :
708 8 : psTile->nOffset = INVALID_OFFSET;
709 8 : psTile->nSize = 0;
710 : }
711 :
712 : // Write the tile list to disk.
713 8 : WriteTileList();
714 :
715 8 : mbModified = false;
716 :
717 8 : oLock.Release();
718 :
719 : // Make sure that the first tile starts on a block boundary.
720 8 : uint64 nLayerSize = GetLayerSize();
721 8 : uint32 nBlockSize = mpoBlockDir->GetBlockSize();
722 :
723 8 : if (nLayerSize % nBlockSize != 0)
724 8 : Resize((nLayerSize / nBlockSize + 1) * nBlockSize);
725 : }
726 :
727 : /************************************************************************/
728 : /* GetDataType() */
729 : /************************************************************************/
730 :
731 : /**
732 : * Gets the data type of the tile layer.
733 : *
734 : * @return The data type of the tile layer.
735 : */
736 140 : const char * BlockTileLayer::GetDataType(void) const
737 : {
738 280 : MutexHolder oLock(mpoTileListMutex);
739 :
740 140 : if (*mszDataType)
741 104 : return mszDataType;
742 :
743 36 : memcpy(mszDataType, mpsTileLayer->szDataType, 4);
744 :
745 36 : int nIter = 3;
746 :
747 90 : while (nIter > 0 && mszDataType[nIter] == ' ')
748 54 : mszDataType[nIter--] = '\0';
749 :
750 36 : return mszDataType;
751 : }
752 :
753 : /************************************************************************/
754 : /* GetCompressType() */
755 : /************************************************************************/
756 :
757 : /**
758 : * Gets the compress type of the tile layer.
759 : *
760 : * @return The compress type of the tile layer.
761 : */
762 38 : const char * BlockTileLayer::GetCompressType(void) const
763 : {
764 76 : MutexHolder oLock(mpoTileListMutex);
765 :
766 38 : if (*mszCompress)
767 18 : return mszCompress;
768 :
769 20 : memcpy(mszCompress, mpsTileLayer->szCompress, 8);
770 :
771 20 : int nIter = 7;
772 :
773 106 : while (nIter > 0 && mszCompress[nIter] == ' ')
774 86 : mszCompress[nIter--] = '\0';
775 :
776 20 : return mszCompress;
777 : }
778 :
779 : } // namespace PCIDSK
|