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