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/asciitilelayer.h"
29 : #include "blockdir/blockfile.h"
30 : #include "core/pcidsk_scanint.h"
31 : #include "pcidsk_exception.h"
32 : #include "pcidsk_buffer.h"
33 : #include <cstdlib>
34 : #include <cstring>
35 : #include <cstdio>
36 : #include <algorithm>
37 : #include <limits>
38 :
39 : using namespace PCIDSK;
40 :
41 : /************************************************************************/
42 : /* AsciiTileLayer() */
43 : /************************************************************************/
44 :
45 : /**
46 : * Constructor.
47 : *
48 : * @param poBlockDir The associated block directory.
49 : * @param nLayer The index of the block layer.
50 : * @param psBlockLayer The block layer info.
51 : * @param psTileLayer The tile layer info.
52 : */
53 22 : AsciiTileLayer::AsciiTileLayer(BlockDir * poBlockDir, uint32 nLayer,
54 : BlockLayerInfo * psBlockLayer,
55 22 : TileLayerInfo * psTileLayer)
56 22 : : BlockTileLayer(poBlockDir, nLayer, psBlockLayer, psTileLayer)
57 : {
58 22 : }
59 :
60 : /************************************************************************/
61 : /* ReadHeader() */
62 : /************************************************************************/
63 :
64 : /**
65 : * Reads the tile layer header from disk.
66 : */
67 5 : void AsciiTileLayer::ReadHeader(void)
68 : {
69 : uint8 abyHeader[128];
70 :
71 5 : uint8 * pabyHeaderIter = abyHeader;
72 :
73 5 : ReadFromLayer(abyHeader, 0, 128);
74 :
75 5 : mpsTileLayer->nXSize = ScanInt8(pabyHeaderIter);
76 5 : pabyHeaderIter += 8;
77 :
78 5 : mpsTileLayer->nYSize = ScanInt8(pabyHeaderIter);
79 5 : pabyHeaderIter += 8;
80 :
81 5 : mpsTileLayer->nTileXSize = ScanInt8(pabyHeaderIter);
82 5 : pabyHeaderIter += 8;
83 :
84 5 : mpsTileLayer->nTileYSize = ScanInt8(pabyHeaderIter);
85 5 : pabyHeaderIter += 8;
86 :
87 5 : memcpy(mpsTileLayer->szDataType, pabyHeaderIter, 4);
88 5 : pabyHeaderIter += 4;
89 : /*
90 : std::string oNoDataValue((char *) pabyHeaderIter,
91 : (char *) pabyHeaderIter + 18);
92 : */
93 5 : mpsTileLayer->bNoDataValid = false;
94 5 : mpsTileLayer->dfNoDataValue = 0.0;
95 5 : pabyHeaderIter += 18;
96 :
97 5 : memcpy(mpsTileLayer->szCompress, pabyHeaderIter, 8);
98 5 : }
99 :
100 : /************************************************************************/
101 : /* WriteTileList() */
102 : /************************************************************************/
103 :
104 : /**
105 : * Writes the tile list to disk.
106 : */
107 4 : void AsciiTileLayer::WriteTileList(void)
108 : {
109 4 : uint32 nTileCount = GetTileCount();
110 :
111 4 : size_t nSize = 128 + nTileCount * 20;
112 :
113 4 : char * pabyTileLayer = (char *) malloc(nSize + 1); // +1 for '\0'.
114 :
115 4 : if (!pabyTileLayer)
116 0 : return ThrowPCIDSKException("Out of memory in AsciiTileLayer::WriteTileList().");
117 :
118 8 : PCIDSKBuffer oTileLayerAutoPtr;
119 4 : oTileLayerAutoPtr.buffer = pabyTileLayer;
120 :
121 : // Write the tile layer header to disk.
122 4 : char * pabyHeaderIter = pabyTileLayer;
123 :
124 4 : memset(pabyTileLayer, ' ', 128);
125 :
126 4 : snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nXSize);
127 4 : pabyHeaderIter += 8;
128 :
129 4 : snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nYSize);
130 4 : pabyHeaderIter += 8;
131 :
132 4 : snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nTileXSize);
133 4 : pabyHeaderIter += 8;
134 :
135 4 : snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nTileYSize);
136 4 : pabyHeaderIter += 8;
137 :
138 4 : memcpy(pabyHeaderIter, mpsTileLayer->szDataType, 4);
139 4 : pabyHeaderIter += 4;
140 :
141 4 : if (mpsTileLayer->bNoDataValid)
142 0 : snprintf(pabyHeaderIter, 19, "%18.10E", mpsTileLayer->dfNoDataValue);
143 4 : pabyHeaderIter += 18;
144 :
145 4 : memcpy(pabyHeaderIter, mpsTileLayer->szCompress, 8);
146 :
147 : // Write the tile list to disk.
148 4 : char * pabyTileListIter = pabyTileLayer + 128;
149 :
150 8 : for (uint32 iTile = 0; iTile < nTileCount; iTile++)
151 : {
152 4 : BlockTileInfo * psTile = &moTileList[iTile];
153 :
154 4 : snprintf(pabyTileListIter, 13, "%12" PCIDSK_FRMT_64_WITHOUT_PREFIX "d", psTile->nOffset);
155 4 : pabyTileListIter += 12;
156 : }
157 :
158 : // We cannot write the offset and the size at the same time because
159 : // snprintf() inserts a '\0' in the first character of the first size.
160 8 : for (uint32 iTile = 0; iTile < nTileCount; iTile++)
161 : {
162 4 : BlockTileInfo * psTile = &moTileList[iTile];
163 :
164 4 : snprintf(pabyTileListIter, 9, "%8d", psTile->nSize);
165 4 : pabyTileListIter += 8;
166 : }
167 :
168 4 : WriteToLayer(pabyTileLayer, 0, nSize);
169 : }
170 :
171 : /************************************************************************/
172 : /* ReadTileList() */
173 : /************************************************************************/
174 :
175 : /**
176 : * Reads the tile list from disk.
177 : */
178 5 : void AsciiTileLayer::ReadTileList(void)
179 : {
180 5 : uint32 nTileCount = GetTileCount();
181 :
182 5 : uint64 nSize = static_cast<uint64>(nTileCount) * 20;
183 :
184 5 : if (128 + nSize > GetLayerSize() || !GetFile()->IsValidFileOffset(128 + nSize))
185 0 : return ThrowPCIDSKException("The tile layer is corrupted.");
186 :
187 : #if SIZEOF_VOIDP < 8
188 : if (nSize > std::numeric_limits<size_t>::max())
189 : return ThrowPCIDSKException("Unable to open extremely large tile layer on 32-bit system.");
190 : #endif
191 :
192 5 : uint8 * pabyTileList = (uint8 *) malloc(static_cast<size_t>(nSize));
193 :
194 5 : if (!pabyTileList)
195 0 : return ThrowPCIDSKException("Out of memory in AsciiTileLayer::ReadTileList().");
196 :
197 5 : PCIDSKBuffer oTileListAutoPtr;
198 5 : oTileListAutoPtr.buffer = (char *) pabyTileList;
199 :
200 5 : ReadFromLayer(pabyTileList, 128, nSize);
201 :
202 5 : uint8 * pabyTileOffsetIter = pabyTileList;
203 5 : uint8 * pabyTileSizeIter = pabyTileList + nTileCount * 12;
204 :
205 : try
206 : {
207 5 : moTileList.resize(nTileCount);
208 : }
209 0 : catch (const std::exception & ex)
210 : {
211 0 : return ThrowPCIDSKException("Out of memory in AsciiTileLayer::ReadTileList(): %s", ex.what());
212 : }
213 :
214 18 : for (uint32 iTile = 0; iTile < nTileCount; iTile++)
215 : {
216 13 : BlockTileInfo * psTile = &moTileList[iTile];
217 :
218 13 : psTile->nOffset = ScanInt12(pabyTileOffsetIter);
219 13 : pabyTileOffsetIter += 12;
220 :
221 13 : psTile->nSize = ScanInt8(pabyTileSizeIter);
222 13 : pabyTileSizeIter += 8;
223 : }
224 : }
|