Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: RIK Reader
4 : * Purpose: All code for RIK Reader
5 : * Author: Daniel Wallner, daniel.wallner@bredband.net
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2005, Daniel Wallner <daniel.wallner@bredband.net>
9 : * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
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 <cfloat>
31 : #include <zlib.h>
32 : #include "gdal_frmts.h"
33 : #include "gdal_pam.h"
34 :
35 : #define RIK_HEADER_DEBUG 0
36 : #define RIK_CLEAR_DEBUG 0
37 : #define RIK_PIXEL_DEBUG 0
38 :
39 : // #define RIK_SINGLE_BLOCK 0
40 :
41 : #define RIK_ALLOW_BLOCK_ERRORS 1
42 :
43 : //
44 : // The RIK file format information was extracted from the trikpanel project:
45 : // http://sourceforge.net/projects/trikpanel/
46 : //
47 : // A RIK file consists of the following elements:
48 : //
49 : // +--------------------+
50 : // | Magic "RIK3" | (Only in RIK version 3)
51 : // +--------------------+
52 : // | Map name | (The first two bytes is the string length)
53 : // +--------------------+
54 : // | Header | (Three different formats exists)
55 : // +--------------------+
56 : // | Color palette |
57 : // +--------------------+
58 : // | Block offset array | (Only in compressed formats)
59 : // +--------------------+
60 : // | Image blocks |
61 : // +--------------------+
62 : //
63 : // All numbers are stored in little endian.
64 : //
65 : // There are four different image block formats:
66 : //
67 : // 1. Uncompressed image block
68 : //
69 : // A stream of palette indexes.
70 : //
71 : // 2. RLE image block
72 : //
73 : // The RLE image block is a stream of byte pairs:
74 : // | Run length - 1 (byte) | Pixel value (byte) | Run length - 1 ...
75 : //
76 : // 3. LZW image block
77 : //
78 : // The LZW image block uses the same LZW encoding as a GIF file
79 : // except that there is no EOF code and maximum code length is 13 bits.
80 : // These blocks are upside down compared to GDAL.
81 : //
82 : // 4. ZLIB image block
83 : //
84 : // These blocks are upside down compared to GDAL.
85 : //
86 :
87 : typedef struct
88 : {
89 : GUInt16 iUnknown;
90 : double fSouth; // Map bounds
91 : double fWest;
92 : double fNorth;
93 : double fEast;
94 : GUInt32 iScale; // Source map scale
95 : float iMPPNum; // Meters per pixel numerator
96 : GUInt32 iMPPDen; // Meters per pixel denominator
97 : // Only used if fSouth < 4000000
98 : GUInt32 iBlockWidth;
99 : GUInt32 iBlockHeight;
100 : GUInt32 iHorBlocks; // Number of horizontal blocks
101 : GUInt32 iVertBlocks; // Number of vertical blocks
102 : // Only used if fSouth >= 4000000
103 : GByte iBitsPerPixel;
104 : GByte iOptions;
105 : } RIKHeader;
106 :
107 : /************************************************************************/
108 : /* ==================================================================== */
109 : /* RIKDataset */
110 : /* ==================================================================== */
111 : /************************************************************************/
112 :
113 : class RIKRasterBand;
114 :
115 : class RIKDataset final : public GDALPamDataset
116 : {
117 : friend class RIKRasterBand;
118 :
119 : VSILFILE *fp;
120 :
121 : OGRSpatialReference m_oSRS{};
122 : double adfTransform[6];
123 :
124 : GUInt32 nBlockXSize;
125 : GUInt32 nBlockYSize;
126 : GUInt32 nHorBlocks;
127 : GUInt32 nVertBlocks;
128 : GUInt32 nFileSize;
129 : GUInt32 *pOffsets;
130 : GByte options;
131 :
132 : GDALColorTable *poColorTable;
133 :
134 : public:
135 : RIKDataset();
136 : ~RIKDataset();
137 :
138 : static GDALDataset *Open(GDALOpenInfo *);
139 : static int Identify(GDALOpenInfo *);
140 :
141 : CPLErr GetGeoTransform(double *padfTransform) override;
142 : const OGRSpatialReference *GetSpatialRef() const override;
143 : };
144 :
145 : /************************************************************************/
146 : /* ==================================================================== */
147 : /* RIKRasterBand */
148 : /* ==================================================================== */
149 : /************************************************************************/
150 :
151 : class RIKRasterBand final : public GDALPamRasterBand
152 : {
153 : friend class RIKDataset;
154 :
155 : public:
156 : RIKRasterBand(RIKDataset *, int);
157 :
158 : virtual CPLErr IReadBlock(int, int, void *) override;
159 : virtual GDALColorInterp GetColorInterpretation() override;
160 : virtual GDALColorTable *GetColorTable() override;
161 : };
162 :
163 : /************************************************************************/
164 : /* RIKRasterBand() */
165 : /************************************************************************/
166 :
167 0 : RIKRasterBand::RIKRasterBand(RIKDataset *poDSIn, int nBandIn)
168 :
169 : {
170 0 : poDS = poDSIn;
171 0 : nBand = nBandIn;
172 :
173 0 : eDataType = GDT_Byte;
174 :
175 0 : nBlockXSize = poDSIn->nBlockXSize;
176 0 : nBlockYSize = poDSIn->nBlockYSize;
177 0 : }
178 :
179 : /************************************************************************/
180 : /* GetNextLZWCode() */
181 : /************************************************************************/
182 :
183 0 : static int GetNextLZWCode(int codeBits, const GByte *blockData,
184 : const GUInt32 blockSize, GUInt32 &filePos,
185 : GUInt32 &fileAlign, int &bitsTaken)
186 :
187 : {
188 0 : if (filePos == fileAlign)
189 : {
190 0 : fileAlign += codeBits;
191 : }
192 :
193 0 : const int BitMask[] = {0x0000, 0x0001, 0x0003, 0x0007,
194 : 0x000f, 0x001f, 0x003f, 0x007f};
195 :
196 0 : int ret = 0;
197 0 : int bitsLeftToGo = codeBits;
198 :
199 0 : while (bitsLeftToGo > 0)
200 : {
201 0 : if (filePos >= blockSize)
202 0 : return -1;
203 :
204 0 : int tmp = blockData[filePos];
205 0 : tmp = tmp >> bitsTaken;
206 :
207 0 : if (bitsLeftToGo < 8)
208 0 : tmp &= BitMask[bitsLeftToGo];
209 :
210 0 : tmp = tmp << (codeBits - bitsLeftToGo);
211 :
212 0 : ret |= tmp;
213 :
214 0 : bitsLeftToGo -= (8 - bitsTaken);
215 0 : bitsTaken = 0;
216 :
217 0 : if (bitsLeftToGo < 0)
218 0 : bitsTaken = 8 + bitsLeftToGo;
219 :
220 0 : if (bitsTaken == 0)
221 0 : filePos++;
222 : }
223 :
224 : #if RIK_PIXEL_DEBUG
225 : printf("c%03X\n", ret); /*ok*/
226 : #endif
227 :
228 0 : return ret;
229 : }
230 :
231 : /************************************************************************/
232 : /* OutputPixel() */
233 : /************************************************************************/
234 :
235 0 : static void OutputPixel(GByte pixel, void *image, GUInt32 imageWidth,
236 : GUInt32 lineBreak, int &imageLine, GUInt32 &imagePos)
237 :
238 : {
239 0 : if (imagePos < imageWidth && imageLine >= 0)
240 0 : reinterpret_cast<GByte *>(image)[imagePos + imageLine * imageWidth] =
241 : pixel;
242 :
243 0 : imagePos++;
244 :
245 : #if RIK_PIXEL_DEBUG
246 : printf("_%02X %d\n", pixel, imagePos); /*ok*/
247 : #endif
248 :
249 : // Check if we need to change line
250 :
251 0 : if (imagePos == lineBreak)
252 : {
253 : #if RIK_PIXEL_DEBUG
254 : printf("\n%d\n", imageLine); /*ok*/
255 : #endif
256 :
257 0 : imagePos = 0;
258 :
259 0 : imageLine--;
260 : }
261 0 : }
262 :
263 : /************************************************************************/
264 : /* IReadBlock() */
265 : /************************************************************************/
266 :
267 0 : CPLErr RIKRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
268 :
269 : {
270 0 : RIKDataset *poRDS = reinterpret_cast<RIKDataset *>(poDS);
271 :
272 0 : const GUInt32 blocks = poRDS->nHorBlocks * poRDS->nVertBlocks;
273 0 : const GUInt32 nBlockIndex = nBlockXOff + nBlockYOff * poRDS->nHorBlocks;
274 0 : const GUInt32 nBlockOffset = poRDS->pOffsets[nBlockIndex];
275 :
276 0 : GUInt32 nBlockSize = poRDS->nFileSize;
277 0 : for (GUInt32 bi = nBlockIndex + 1; bi < blocks; bi++)
278 : {
279 0 : if (poRDS->pOffsets[bi])
280 : {
281 0 : nBlockSize = poRDS->pOffsets[bi];
282 0 : break;
283 : }
284 : }
285 0 : nBlockSize -= nBlockOffset;
286 :
287 0 : const GUInt32 pixels = poRDS->nBlockXSize * poRDS->nBlockYSize;
288 :
289 0 : if (!nBlockOffset || !nBlockSize
290 : #ifdef RIK_SINGLE_BLOCK
291 : || nBlockIndex != RIK_SINGLE_BLOCK
292 : #endif
293 : )
294 : {
295 0 : memset(pImage, 0, pixels);
296 0 : return CE_None;
297 : }
298 :
299 0 : VSIFSeekL(poRDS->fp, nBlockOffset, SEEK_SET);
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* Read uncompressed block. */
303 : /* -------------------------------------------------------------------- */
304 :
305 0 : if (poRDS->options == 0x00 || poRDS->options == 0x40)
306 : {
307 0 : VSIFReadL(pImage, 1, pixels, poRDS->fp);
308 0 : return CE_None;
309 : }
310 :
311 : // Read block to memory
312 : GByte *blockData =
313 0 : reinterpret_cast<GByte *>(VSI_MALLOC_VERBOSE(nBlockSize));
314 0 : if (blockData == nullptr)
315 0 : return CE_Failure;
316 0 : if (VSIFReadL(blockData, 1, nBlockSize, poRDS->fp) != nBlockSize)
317 : {
318 0 : VSIFree(blockData);
319 0 : return CE_Failure;
320 : }
321 0 : memset(pImage, 0, pixels);
322 :
323 : /* -------------------------------------------------------------------- */
324 : /* Read RLE block. */
325 : /* -------------------------------------------------------------------- */
326 0 : GUInt32 filePos = 0;
327 0 : GUInt32 imagePos = 0;
328 :
329 0 : if (poRDS->options == 0x01 || poRDS->options == 0x41)
330 : {
331 0 : while (filePos + 1 < nBlockSize && imagePos < pixels)
332 : {
333 0 : GByte count = blockData[filePos++];
334 0 : GByte color = blockData[filePos++];
335 :
336 0 : for (GByte i = 0; imagePos < pixels && i <= count; i++)
337 : {
338 0 : reinterpret_cast<GByte *>(pImage)[imagePos++] = color;
339 : }
340 0 : }
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Read LZW block. */
345 : /* -------------------------------------------------------------------- */
346 :
347 0 : else if (poRDS->options == 0x0b)
348 : {
349 : try
350 : {
351 0 : if (nBlockSize < 5)
352 : {
353 0 : throw "Not enough bytes";
354 : }
355 :
356 0 : const bool LZW_HAS_CLEAR_CODE = !!(blockData[4] & 0x80);
357 0 : const int LZW_MAX_BITS = blockData[4] & 0x1f; // Max 13
358 0 : if (LZW_MAX_BITS > 13)
359 : {
360 0 : throw "Invalid LZW_MAX_BITS";
361 : }
362 0 : const int LZW_BITS_PER_PIXEL = 8;
363 0 : const int LZW_OFFSET = 5;
364 :
365 0 : const int LZW_CLEAR = 1 << LZW_BITS_PER_PIXEL;
366 0 : const int LZW_CODES = 1 << LZW_MAX_BITS;
367 0 : const int LZW_NO_SUCH_CODE = LZW_CODES + 1;
368 :
369 0 : int lastAdded = LZW_HAS_CLEAR_CODE ? LZW_CLEAR : LZW_CLEAR - 1;
370 0 : int codeBits = LZW_BITS_PER_PIXEL + 1;
371 :
372 : int code;
373 : int lastCode;
374 : GByte lastOutput;
375 0 : int bitsTaken = 0;
376 :
377 : int prefix[8192]; // only need LZW_CODES for size.
378 : GByte character[8192]; // only need LZW_CODES for size.
379 :
380 0 : for (int i = 0; i < LZW_CLEAR; i++)
381 0 : character[i] = static_cast<GByte>(i);
382 0 : for (int i = 0; i < LZW_CODES; i++)
383 0 : prefix[i] = LZW_NO_SUCH_CODE;
384 :
385 0 : filePos = LZW_OFFSET;
386 0 : GUInt32 fileAlign = LZW_OFFSET;
387 0 : int imageLine = poRDS->nBlockYSize - 1;
388 :
389 0 : GUInt32 lineBreak = poRDS->nBlockXSize;
390 :
391 : // 32 bit alignment
392 0 : lineBreak += 3;
393 0 : lineBreak &= 0xfffffffc;
394 :
395 0 : code = GetNextLZWCode(codeBits, blockData, nBlockSize, filePos,
396 : fileAlign, bitsTaken);
397 0 : if (code < 0)
398 : {
399 0 : throw "Not enough bytes";
400 : }
401 :
402 0 : OutputPixel(static_cast<GByte>(code), pImage, poRDS->nBlockXSize,
403 : lineBreak, imageLine, imagePos);
404 0 : lastOutput = static_cast<GByte>(code);
405 :
406 0 : while (imageLine >= 0 &&
407 0 : (imageLine || imagePos < poRDS->nBlockXSize) &&
408 0 : filePos < nBlockSize)
409 : {
410 0 : lastCode = code;
411 0 : code = GetNextLZWCode(codeBits, blockData, nBlockSize, filePos,
412 : fileAlign, bitsTaken);
413 0 : if (code < 0)
414 : {
415 0 : throw "Not enough bytes";
416 : }
417 :
418 0 : if (LZW_HAS_CLEAR_CODE && code == LZW_CLEAR)
419 : {
420 : #if RIK_CLEAR_DEBUG
421 : CPLDebug("RIK",
422 : "Clearing block %d\n"
423 : " x=%d y=%d\n"
424 : " pos=%d size=%d\n",
425 : nBlockIndex, imagePos, imageLine, filePos,
426 : nBlockSize);
427 : #endif
428 :
429 : // Clear prefix table
430 0 : for (int i = LZW_CLEAR; i < LZW_CODES; i++)
431 0 : prefix[i] = LZW_NO_SUCH_CODE;
432 0 : lastAdded = LZW_CLEAR;
433 0 : codeBits = LZW_BITS_PER_PIXEL + 1;
434 :
435 0 : filePos = fileAlign;
436 0 : bitsTaken = 0;
437 :
438 0 : code = GetNextLZWCode(codeBits, blockData, nBlockSize,
439 : filePos, fileAlign, bitsTaken);
440 0 : if (code < 0)
441 : {
442 0 : throw "Not enough bytes";
443 : }
444 :
445 0 : if (code > lastAdded)
446 : {
447 0 : throw "Clear Error";
448 : }
449 :
450 0 : OutputPixel((GByte)code, pImage, poRDS->nBlockXSize,
451 : lineBreak, imageLine, imagePos);
452 0 : lastOutput = (GByte)code;
453 : }
454 : else
455 : {
456 : // Set-up decoding
457 :
458 : GByte stack[8192]; // only need LZW_CODES for size.
459 :
460 0 : int stackPtr = 0;
461 0 : int decodeCode = code;
462 :
463 0 : if (code == lastAdded + 1)
464 : {
465 : // Handle special case
466 0 : *stack = lastOutput;
467 0 : stackPtr = 1;
468 0 : decodeCode = lastCode;
469 : }
470 0 : else if (code > lastAdded + 1)
471 : {
472 0 : throw "Too high code";
473 : }
474 :
475 : // Decode
476 :
477 0 : int i = 0;
478 0 : while (++i < LZW_CODES && decodeCode >= LZW_CLEAR &&
479 : decodeCode < LZW_NO_SUCH_CODE)
480 : {
481 0 : stack[stackPtr++] = character[decodeCode];
482 0 : decodeCode = prefix[decodeCode];
483 : }
484 0 : stack[stackPtr++] = static_cast<GByte>(decodeCode);
485 :
486 0 : if (i == LZW_CODES || decodeCode >= LZW_NO_SUCH_CODE)
487 : {
488 0 : throw "Decode error";
489 : }
490 :
491 : // Output stack
492 :
493 0 : lastOutput = stack[stackPtr - 1];
494 :
495 0 : while (stackPtr != 0 && imagePos < pixels)
496 : {
497 0 : OutputPixel(stack[--stackPtr], pImage,
498 : poRDS->nBlockXSize, lineBreak, imageLine,
499 : imagePos);
500 : }
501 :
502 : // Add code to string table
503 :
504 0 : if (lastCode != LZW_NO_SUCH_CODE &&
505 0 : lastAdded != LZW_CODES - 1)
506 : {
507 0 : ++lastAdded;
508 0 : if (lastAdded >= 8192)
509 : {
510 0 : throw "Decode error";
511 : }
512 0 : prefix[lastAdded] = lastCode;
513 0 : character[lastAdded] = lastOutput;
514 : }
515 :
516 : // Check if we need to use more bits
517 :
518 0 : if (lastAdded == (1 << codeBits) - 1 &&
519 : codeBits != LZW_MAX_BITS)
520 : {
521 0 : codeBits++;
522 :
523 0 : filePos = fileAlign;
524 0 : bitsTaken = 0;
525 : }
526 : }
527 : }
528 : }
529 0 : catch (const char *errStr)
530 : {
531 : #if RIK_ALLOW_BLOCK_ERRORS
532 0 : CPLDebug("RIK",
533 : "LZW Decompress Failed: %s\n"
534 : " blocks: %d\n"
535 : " blockindex: %d\n"
536 : " blockoffset: %X\n"
537 : " blocksize: %d\n",
538 : errStr, blocks, nBlockIndex, nBlockOffset, nBlockSize);
539 : #else
540 : CPLFree(blockData);
541 : CPLError(CE_Failure, CPLE_AppDefined,
542 : "RIK decompression failed: %s", errStr);
543 : return CE_Failure;
544 : #endif
545 : }
546 : }
547 :
548 : /* -------------------------------------------------------------------- */
549 : /* Read ZLIB block. */
550 : /* -------------------------------------------------------------------- */
551 :
552 0 : else if (poRDS->options == 0x0d)
553 : {
554 0 : uLong destLen = pixels;
555 0 : Byte *upsideDown = static_cast<Byte *>(CPLMalloc(pixels));
556 :
557 0 : if (uncompress(upsideDown, &destLen, blockData, nBlockSize) != Z_OK)
558 : {
559 0 : CPLDebug("RIK", "Deflate compression failed on block %u",
560 : nBlockIndex);
561 : }
562 :
563 0 : for (GUInt32 i = 0; i < poRDS->nBlockYSize; i++)
564 : {
565 0 : memcpy(reinterpret_cast<Byte *>(pImage) + poRDS->nBlockXSize * i,
566 0 : upsideDown +
567 0 : poRDS->nBlockXSize * (poRDS->nBlockYSize - i - 1),
568 0 : poRDS->nBlockXSize);
569 : }
570 :
571 0 : CPLFree(upsideDown);
572 : }
573 :
574 0 : CPLFree(blockData);
575 :
576 0 : return CE_None;
577 : }
578 :
579 : /************************************************************************/
580 : /* GetColorInterpretation() */
581 : /************************************************************************/
582 :
583 0 : GDALColorInterp RIKRasterBand::GetColorInterpretation()
584 :
585 : {
586 0 : return GCI_PaletteIndex;
587 : }
588 :
589 : /************************************************************************/
590 : /* GetColorTable() */
591 : /************************************************************************/
592 :
593 0 : GDALColorTable *RIKRasterBand::GetColorTable()
594 :
595 : {
596 0 : RIKDataset *poRDS = reinterpret_cast<RIKDataset *>(poDS);
597 :
598 0 : return poRDS->poColorTable;
599 : }
600 :
601 : /************************************************************************/
602 : /* ==================================================================== */
603 : /* RIKDataset */
604 : /* ==================================================================== */
605 : /************************************************************************/
606 :
607 : /************************************************************************/
608 : /* RIKDataset() */
609 : /************************************************************************/
610 :
611 0 : RIKDataset::RIKDataset()
612 : : fp(nullptr), nBlockXSize(0), nBlockYSize(0), nHorBlocks(0),
613 : nVertBlocks(0), nFileSize(0), pOffsets(nullptr), options(0),
614 0 : poColorTable(nullptr)
615 :
616 : {
617 0 : m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
618 0 : m_oSRS.importFromWkt(
619 : "PROJCS[\"RT90 2.5 gon "
620 : "V\",GEOGCS[\"RT90\",DATUM[\"Rikets_koordinatsystem_1990\",SPHEROID["
621 : "\"Bessel "
622 : "1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],TOWGS84["
623 : "414.1055246174,41.3265500042,603.0582474221,-0.8551163377,2."
624 : "1413174055,-7.0227298286,0],AUTHORITY[\"EPSG\",\"6124\"]],PRIMEM["
625 : "\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0."
626 : "0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\","
627 : "\"4124\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_"
628 : "of_origin\",0],PARAMETER[\"central_meridian\",15.80827777777778],"
629 : "PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",1500000],"
630 : "PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\","
631 : "\"9001\"]],AUTHORITY[\"EPSG\",\"3021\"]]");
632 0 : memset(adfTransform, 0, sizeof(adfTransform));
633 0 : }
634 :
635 : /************************************************************************/
636 : /* ~RIKDataset() */
637 : /************************************************************************/
638 :
639 0 : RIKDataset::~RIKDataset()
640 :
641 : {
642 0 : FlushCache(true);
643 0 : CPLFree(pOffsets);
644 0 : if (fp != nullptr)
645 0 : VSIFCloseL(fp);
646 0 : delete poColorTable;
647 0 : }
648 :
649 : /************************************************************************/
650 : /* GetGeoTransform() */
651 : /************************************************************************/
652 :
653 0 : CPLErr RIKDataset::GetGeoTransform(double *padfTransform)
654 :
655 : {
656 0 : memcpy(padfTransform, &adfTransform, sizeof(double) * 6);
657 :
658 0 : return CE_None;
659 : }
660 :
661 : /************************************************************************/
662 : /* GetSpatialRef() */
663 : /************************************************************************/
664 :
665 0 : const OGRSpatialReference *RIKDataset::GetSpatialRef() const
666 :
667 : {
668 0 : return &m_oSRS;
669 : }
670 :
671 : /************************************************************************/
672 : /* GetRikString() */
673 : /************************************************************************/
674 :
675 733 : static GUInt16 GetRikString(VSILFILE *fp, char *str, GUInt16 strLength)
676 :
677 : {
678 : GUInt16 actLength;
679 :
680 733 : VSIFReadL(&actLength, 1, sizeof(actLength), fp);
681 : #ifdef CPL_MSB
682 : CPL_SWAP16PTR(&actLength);
683 : #endif
684 :
685 733 : if (actLength + 2 > strLength)
686 : {
687 0 : return actLength;
688 : }
689 :
690 733 : VSIFReadL(str, 1, actLength, fp);
691 :
692 733 : str[actLength] = '\0';
693 :
694 733 : return actLength;
695 : }
696 :
697 : /************************************************************************/
698 : /* Identify() */
699 : /************************************************************************/
700 :
701 49305 : int RIKDataset::Identify(GDALOpenInfo *poOpenInfo)
702 :
703 : {
704 49305 : if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 50)
705 45553 : return FALSE;
706 :
707 3752 : if (STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RIK3"))
708 : {
709 0 : return TRUE;
710 : }
711 : else
712 : {
713 : GUInt16 actLength;
714 3752 : memcpy(&actLength, poOpenInfo->pabyHeader, 2);
715 : #ifdef CPL_MSB
716 : CPL_SWAP16PTR(&actLength);
717 : #endif
718 3752 : if (actLength + 2 > 1024)
719 : {
720 2193 : return FALSE;
721 : }
722 1559 : if (actLength == 0)
723 1488 : return -1;
724 :
725 2560 : for (int i = 0; i < actLength; i++)
726 : {
727 2554 : if (poOpenInfo->pabyHeader[2 + i] == 0)
728 65 : return FALSE;
729 : }
730 :
731 6 : if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "rik"))
732 0 : return TRUE;
733 :
734 : // We really need Open to be able to conclude
735 6 : return -1;
736 : }
737 : }
738 :
739 : /************************************************************************/
740 : /* Open() */
741 : /************************************************************************/
742 :
743 733 : GDALDataset *RIKDataset::Open(GDALOpenInfo *poOpenInfo)
744 :
745 : {
746 733 : if (Identify(poOpenInfo) == FALSE)
747 0 : return nullptr;
748 :
749 733 : bool rik3header = false;
750 :
751 733 : if (STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RIK3"))
752 : {
753 0 : rik3header = true;
754 0 : VSIFSeekL(poOpenInfo->fpL, 4, SEEK_SET);
755 : }
756 : else
757 733 : VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Read the map name. */
761 : /* -------------------------------------------------------------------- */
762 :
763 : char name[1024];
764 :
765 733 : GUInt16 nameLength = GetRikString(poOpenInfo->fpL, name, sizeof(name));
766 :
767 733 : if (nameLength > sizeof(name) - 1)
768 : {
769 0 : return nullptr;
770 : }
771 :
772 733 : if (!rik3header)
773 : {
774 733 : if (nameLength == 0 || nameLength != strlen(name))
775 730 : return nullptr;
776 : }
777 :
778 : /* -------------------------------------------------------------------- */
779 : /* Read the header. */
780 : /* -------------------------------------------------------------------- */
781 :
782 : RIKHeader header;
783 : double metersPerPixel;
784 :
785 3 : const char *headerType = "RIK3";
786 :
787 3 : if (rik3header)
788 : {
789 : /* --------------------------------------------------------------------
790 : */
791 : /* RIK3 header. */
792 : /* --------------------------------------------------------------------
793 : */
794 :
795 : // Read projection name
796 :
797 : char projection[1024];
798 :
799 : GUInt16 projLength =
800 0 : GetRikString(poOpenInfo->fpL, projection, sizeof(projection));
801 :
802 0 : if (projLength > sizeof(projection) - 1)
803 : {
804 : // Unreasonable string length, assume wrong format
805 0 : return nullptr;
806 : }
807 :
808 : // Read unknown string
809 :
810 0 : /*projLength =*/GetRikString(poOpenInfo->fpL, projection,
811 : sizeof(projection));
812 :
813 : // Read map north edge
814 :
815 : char tmpStr[16];
816 :
817 : GUInt16 tmpLength =
818 0 : GetRikString(poOpenInfo->fpL, tmpStr, sizeof(tmpStr));
819 :
820 0 : if (tmpLength > sizeof(tmpStr) - 1)
821 : {
822 : // Unreasonable string length, assume wrong format
823 0 : return nullptr;
824 : }
825 :
826 0 : header.fNorth = CPLAtof(tmpStr);
827 :
828 : // Read map west edge
829 :
830 0 : tmpLength = GetRikString(poOpenInfo->fpL, tmpStr, sizeof(tmpStr));
831 :
832 0 : if (tmpLength > sizeof(tmpStr) - 1)
833 : {
834 : // Unreasonable string length, assume wrong format
835 0 : return nullptr;
836 : }
837 :
838 0 : header.fWest = CPLAtof(tmpStr);
839 :
840 : // Read binary values
841 :
842 0 : VSIFReadL(&header.iScale, 1, sizeof(header.iScale), poOpenInfo->fpL);
843 0 : VSIFReadL(&header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fpL);
844 0 : VSIFReadL(&header.iBlockWidth, 1, sizeof(header.iBlockWidth),
845 : poOpenInfo->fpL);
846 0 : VSIFReadL(&header.iBlockHeight, 1, sizeof(header.iBlockHeight),
847 : poOpenInfo->fpL);
848 0 : VSIFReadL(&header.iHorBlocks, 1, sizeof(header.iHorBlocks),
849 : poOpenInfo->fpL);
850 0 : VSIFReadL(&header.iVertBlocks, 1, sizeof(header.iVertBlocks),
851 : poOpenInfo->fpL);
852 : #ifdef CPL_MSB
853 : CPL_SWAP32PTR(&header.iScale);
854 : CPL_SWAP32PTR(&header.iMPPNum);
855 : CPL_SWAP32PTR(&header.iBlockWidth);
856 : CPL_SWAP32PTR(&header.iBlockHeight);
857 : CPL_SWAP32PTR(&header.iHorBlocks);
858 : CPL_SWAP32PTR(&header.iVertBlocks);
859 : #endif
860 0 : if (header.iMPPNum == 0)
861 0 : return nullptr;
862 :
863 0 : VSIFReadL(&header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel),
864 : poOpenInfo->fpL);
865 0 : VSIFReadL(&header.iOptions, 1, sizeof(header.iOptions),
866 : poOpenInfo->fpL);
867 0 : header.iUnknown = header.iOptions;
868 0 : VSIFReadL(&header.iOptions, 1, sizeof(header.iOptions),
869 : poOpenInfo->fpL);
870 :
871 0 : header.fSouth =
872 0 : header.fNorth - static_cast<double>(header.iVertBlocks) *
873 0 : header.iBlockHeight * header.iMPPNum;
874 0 : header.fEast = header.fWest + static_cast<double>(header.iHorBlocks) *
875 0 : header.iBlockWidth * header.iMPPNum;
876 :
877 0 : metersPerPixel = header.iMPPNum;
878 : }
879 : else
880 : {
881 : /* --------------------------------------------------------------------
882 : */
883 : /* Old RIK header. */
884 : /* --------------------------------------------------------------------
885 : */
886 :
887 3 : VSIFReadL(&header.iUnknown, 1, sizeof(header.iUnknown),
888 : poOpenInfo->fpL);
889 3 : VSIFReadL(&header.fSouth, 1, sizeof(header.fSouth), poOpenInfo->fpL);
890 3 : VSIFReadL(&header.fWest, 1, sizeof(header.fWest), poOpenInfo->fpL);
891 3 : VSIFReadL(&header.fNorth, 1, sizeof(header.fNorth), poOpenInfo->fpL);
892 3 : VSIFReadL(&header.fEast, 1, sizeof(header.fEast), poOpenInfo->fpL);
893 3 : VSIFReadL(&header.iScale, 1, sizeof(header.iScale), poOpenInfo->fpL);
894 3 : VSIFReadL(&header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fpL);
895 : #ifdef CPL_MSB
896 : CPL_SWAP64PTR(&header.fSouth);
897 : CPL_SWAP64PTR(&header.fWest);
898 : CPL_SWAP64PTR(&header.fNorth);
899 : CPL_SWAP64PTR(&header.fEast);
900 : CPL_SWAP32PTR(&header.iScale);
901 : CPL_SWAP32PTR(&header.iMPPNum);
902 : #endif
903 :
904 3 : if (!CPLIsFinite(header.fSouth) || !CPLIsFinite(header.fWest) ||
905 3 : !CPLIsFinite(header.fNorth) || !CPLIsFinite(header.fEast) ||
906 3 : header.iMPPNum == 0)
907 : {
908 0 : return nullptr;
909 : }
910 :
911 3 : const bool offsetBounds = header.fSouth < 4000000;
912 :
913 3 : header.iMPPDen = 1;
914 :
915 3 : if (offsetBounds)
916 : {
917 3 : header.fSouth += 4002995;
918 3 : header.fNorth += 5004000;
919 3 : header.fWest += 201000;
920 3 : header.fEast += 302005;
921 :
922 3 : VSIFReadL(&header.iMPPDen, 1, sizeof(header.iMPPDen),
923 : poOpenInfo->fpL);
924 : #ifdef CPL_MSB
925 : CPL_SWAP32PTR(&header.iMPPDen);
926 : #endif
927 3 : if (header.iMPPDen == 0)
928 0 : return nullptr;
929 :
930 3 : headerType = "RIK1";
931 : }
932 : else
933 : {
934 0 : headerType = "RIK2";
935 : }
936 :
937 3 : metersPerPixel = header.iMPPNum / static_cast<double>(header.iMPPDen);
938 :
939 3 : VSIFReadL(&header.iBlockWidth, 1, sizeof(header.iBlockWidth),
940 : poOpenInfo->fpL);
941 3 : VSIFReadL(&header.iBlockHeight, 1, sizeof(header.iBlockHeight),
942 : poOpenInfo->fpL);
943 3 : VSIFReadL(&header.iHorBlocks, 1, sizeof(header.iHorBlocks),
944 : poOpenInfo->fpL);
945 : #ifdef CPL_MSB
946 : CPL_SWAP32PTR(&header.iBlockWidth);
947 : CPL_SWAP32PTR(&header.iBlockHeight);
948 : CPL_SWAP32PTR(&header.iHorBlocks);
949 : #endif
950 :
951 3 : if ((header.iBlockWidth > 2000) || (header.iBlockWidth < 10) ||
952 0 : (header.iBlockHeight > 2000) || (header.iBlockHeight < 10))
953 3 : return nullptr;
954 :
955 0 : if (!offsetBounds)
956 : {
957 0 : VSIFReadL(&header.iVertBlocks, 1, sizeof(header.iVertBlocks),
958 : poOpenInfo->fpL);
959 : #ifdef CPL_MSB
960 : CPL_SWAP32PTR(&header.iVertBlocks);
961 : #endif
962 : }
963 :
964 0 : if (offsetBounds || !header.iVertBlocks)
965 : {
966 0 : double dfVertBlocks = ceil((header.fNorth - header.fSouth) /
967 0 : (header.iBlockHeight * metersPerPixel));
968 0 : if (dfVertBlocks < 1 || dfVertBlocks > INT_MAX)
969 0 : return nullptr;
970 0 : header.iVertBlocks = static_cast<GUInt32>(dfVertBlocks);
971 : }
972 :
973 : #if RIK_HEADER_DEBUG
974 : CPLDebug("RIK", "Original vertical blocks %d\n", header.iVertBlocks);
975 : #endif
976 :
977 0 : VSIFReadL(&header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel),
978 : poOpenInfo->fpL);
979 :
980 0 : if (header.iBitsPerPixel != 8)
981 : {
982 0 : CPLError(CE_Failure, CPLE_OpenFailed,
983 : "File %s has unsupported number of bits per pixel.\n",
984 : poOpenInfo->pszFilename);
985 0 : return nullptr;
986 : }
987 :
988 0 : VSIFReadL(&header.iOptions, 1, sizeof(header.iOptions),
989 : poOpenInfo->fpL);
990 :
991 0 : if (header.iOptions != 0x00 && // Uncompressed
992 0 : header.iOptions != 0x40 && // Uncompressed
993 0 : header.iOptions != 0x01 && // RLE
994 0 : header.iOptions != 0x41 && // RLE
995 0 : header.iOptions != 0x0B && // LZW
996 0 : header.iOptions != 0x0D) // ZLIB
997 : {
998 0 : CPLError(CE_Failure, CPLE_OpenFailed,
999 : "File %s. Unknown map options.\n",
1000 : poOpenInfo->pszFilename);
1001 0 : return nullptr;
1002 : }
1003 : }
1004 :
1005 0 : if (header.iBlockWidth == 0 || header.iHorBlocks == 0 ||
1006 0 : header.iBlockWidth >= INT_MAX / header.iHorBlocks ||
1007 0 : header.iBlockHeight == 0 || header.iVertBlocks == 0 ||
1008 0 : header.iBlockHeight >= INT_MAX / header.iVertBlocks ||
1009 0 : header.iBlockHeight >= INT_MAX / header.iBlockWidth ||
1010 0 : header.iVertBlocks >= INT_MAX / (int)sizeof(GUInt32) ||
1011 0 : header.iHorBlocks >=
1012 0 : INT_MAX / (header.iVertBlocks * (int)sizeof(GUInt32)))
1013 : {
1014 0 : return nullptr;
1015 : }
1016 :
1017 : /* -------------------------------------------------------------------- */
1018 : /* Read the palette. */
1019 : /* -------------------------------------------------------------------- */
1020 :
1021 : GByte palette[768];
1022 :
1023 0 : for (GUInt16 i = 0; i < 256; i++)
1024 : {
1025 0 : VSIFReadL(&palette[i * 3 + 2], 1, 1, poOpenInfo->fpL);
1026 0 : VSIFReadL(&palette[i * 3 + 1], 1, 1, poOpenInfo->fpL);
1027 0 : VSIFReadL(&palette[i * 3 + 0], 1, 1, poOpenInfo->fpL);
1028 : }
1029 :
1030 : /* -------------------------------------------------------------------- */
1031 : /* Find block offsets. */
1032 : /* -------------------------------------------------------------------- */
1033 :
1034 0 : GUInt32 blocks = header.iHorBlocks * header.iVertBlocks;
1035 : GUInt32 *offsets =
1036 0 : reinterpret_cast<GUInt32 *>(VSIMalloc(blocks * sizeof(GUInt32)));
1037 :
1038 0 : if (!offsets)
1039 : {
1040 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1041 : "File %s. Unable to allocate offset table.\n",
1042 : poOpenInfo->pszFilename);
1043 0 : return nullptr;
1044 : }
1045 :
1046 0 : if (header.iOptions == 0x00)
1047 : {
1048 0 : offsets[0] = static_cast<GUInt32>(VSIFTellL(poOpenInfo->fpL));
1049 :
1050 0 : if (VSIFEofL(poOpenInfo->fpL))
1051 : {
1052 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1053 : "File %s. Read past end of file.\n",
1054 : poOpenInfo->pszFilename);
1055 0 : CPLFree(offsets);
1056 0 : return nullptr;
1057 : }
1058 :
1059 0 : VSIFSeekL(poOpenInfo->fpL, 0, SEEK_END);
1060 0 : vsi_l_offset nBigFileSize = VSIFTellL(poOpenInfo->fpL);
1061 0 : if (nBigFileSize > UINT_MAX)
1062 0 : nBigFileSize = UINT_MAX;
1063 0 : GUInt32 fileSize = static_cast<GUInt32>(nBigFileSize);
1064 :
1065 0 : GUInt32 nBlocksFromFileSize =
1066 0 : (fileSize - offsets[0]) /
1067 0 : (header.iBlockWidth * header.iBlockHeight);
1068 0 : if (nBlocksFromFileSize < blocks)
1069 : {
1070 0 : blocks = nBlocksFromFileSize;
1071 0 : header.iVertBlocks = blocks / header.iHorBlocks;
1072 : }
1073 :
1074 0 : if (header.iVertBlocks == 0)
1075 : {
1076 0 : CPLError(CE_Failure, CPLE_OpenFailed, "File %s too short.\n",
1077 : poOpenInfo->pszFilename);
1078 0 : CPLFree(offsets);
1079 0 : return nullptr;
1080 : }
1081 :
1082 0 : for (GUInt32 i = 1; i < blocks; i++)
1083 : {
1084 0 : offsets[i] =
1085 0 : offsets[i - 1] + header.iBlockWidth * header.iBlockHeight;
1086 : }
1087 : }
1088 : else
1089 : {
1090 0 : for (GUInt32 i = 0; i < blocks; i++)
1091 : {
1092 0 : if (VSIFReadL(&offsets[i], sizeof(offsets[i]), 1,
1093 0 : poOpenInfo->fpL) != 1)
1094 0 : break;
1095 : #ifdef CPL_MSB
1096 : CPL_SWAP32PTR(&offsets[i]);
1097 : #endif
1098 0 : if (rik3header)
1099 : {
1100 : GUInt32 blockSize;
1101 0 : if (VSIFReadL(&blockSize, sizeof(blockSize), 1,
1102 0 : poOpenInfo->fpL) != 1)
1103 0 : break;
1104 : #ifdef CPL_MSB
1105 : CPL_SWAP32PTR(&blockSize);
1106 : #endif
1107 : }
1108 : }
1109 : }
1110 :
1111 : /* -------------------------------------------------------------------- */
1112 : /* Final checks. */
1113 : /* -------------------------------------------------------------------- */
1114 :
1115 : // File size
1116 :
1117 0 : if (VSIFEofL(poOpenInfo->fpL))
1118 : {
1119 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1120 : "File %s. Read past end of file.\n", poOpenInfo->pszFilename);
1121 0 : CPLFree(offsets);
1122 0 : return nullptr;
1123 : }
1124 :
1125 0 : VSIFSeekL(poOpenInfo->fpL, 0, SEEK_END);
1126 0 : GUInt32 fileSize = static_cast<GUInt32>(VSIFTellL(poOpenInfo->fpL));
1127 :
1128 : #if RIK_HEADER_DEBUG
1129 : CPLDebug("RIK", "File size %d\n", fileSize);
1130 : #endif
1131 :
1132 : // Make sure the offset table is valid
1133 :
1134 0 : GUInt32 lastoffset = 0;
1135 :
1136 0 : for (GUInt32 y = 0; y < header.iVertBlocks; y++)
1137 : {
1138 0 : for (GUInt32 x = 0; x < header.iHorBlocks; x++)
1139 : {
1140 0 : if (!offsets[x + y * header.iHorBlocks])
1141 : {
1142 0 : continue;
1143 : }
1144 :
1145 0 : if (offsets[x + y * header.iHorBlocks] >= fileSize)
1146 : {
1147 0 : if (!y)
1148 : {
1149 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1150 : "File %s too short.\n", poOpenInfo->pszFilename);
1151 0 : CPLFree(offsets);
1152 0 : return nullptr;
1153 : }
1154 0 : header.iVertBlocks = y;
1155 0 : break;
1156 : }
1157 :
1158 0 : if (offsets[x + y * header.iHorBlocks] < lastoffset)
1159 : {
1160 0 : if (!y)
1161 : {
1162 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1163 : "File %s. Corrupt offset table.\n",
1164 : poOpenInfo->pszFilename);
1165 0 : CPLFree(offsets);
1166 0 : return nullptr;
1167 : }
1168 0 : header.iVertBlocks = y;
1169 0 : break;
1170 : }
1171 :
1172 0 : lastoffset = offsets[x + y * header.iHorBlocks];
1173 : }
1174 : }
1175 :
1176 : #if RIK_HEADER_DEBUG
1177 : CPLDebug("RIK",
1178 : "first offset %d\n"
1179 : "last offset %d\n",
1180 : offsets[0], lastoffset);
1181 : #endif
1182 :
1183 0 : const char *compression = "RLE";
1184 :
1185 0 : if (header.iOptions == 0x00 || header.iOptions == 0x40)
1186 0 : compression = "Uncompressed";
1187 0 : if (header.iOptions == 0x0b)
1188 0 : compression = "LZW";
1189 0 : if (header.iOptions == 0x0d)
1190 0 : compression = "ZLIB";
1191 :
1192 0 : CPLDebug("RIK",
1193 : "RIK file parameters:\n"
1194 : " name: %s\n"
1195 : " header: %s\n"
1196 : " unknown: 0x%X\n"
1197 : " south: %f\n"
1198 : " west: %f\n"
1199 : " north: %f\n"
1200 : " east: %f\n"
1201 : " original scale: %d\n"
1202 : " meters per pixel: %f\n"
1203 : " block width: %d\n"
1204 : " block height: %d\n"
1205 : " horizontal blocks: %d\n"
1206 : " vertical blocks: %d\n"
1207 : " bits per pixel: %d\n"
1208 : " options: 0x%X\n"
1209 : " compression: %s\n",
1210 0 : name, headerType, header.iUnknown, header.fSouth, header.fWest,
1211 : header.fNorth, header.fEast, header.iScale, metersPerPixel,
1212 : header.iBlockWidth, header.iBlockHeight, header.iHorBlocks,
1213 0 : header.iVertBlocks, header.iBitsPerPixel, header.iOptions,
1214 : compression);
1215 :
1216 : /* -------------------------------------------------------------------- */
1217 : /* Create a corresponding GDALDataset. */
1218 : /* -------------------------------------------------------------------- */
1219 :
1220 0 : RIKDataset *poDS = new RIKDataset();
1221 :
1222 0 : poDS->fp = poOpenInfo->fpL;
1223 0 : poOpenInfo->fpL = nullptr;
1224 :
1225 0 : poDS->adfTransform[0] = header.fWest - metersPerPixel / 2.0;
1226 0 : poDS->adfTransform[1] = metersPerPixel;
1227 0 : poDS->adfTransform[2] = 0.0;
1228 0 : poDS->adfTransform[3] = header.fNorth + metersPerPixel / 2.0;
1229 0 : poDS->adfTransform[4] = 0.0;
1230 0 : poDS->adfTransform[5] = -metersPerPixel;
1231 :
1232 0 : poDS->nBlockXSize = header.iBlockWidth;
1233 0 : poDS->nBlockYSize = header.iBlockHeight;
1234 0 : poDS->nHorBlocks = header.iHorBlocks;
1235 0 : poDS->nVertBlocks = header.iVertBlocks;
1236 0 : poDS->pOffsets = offsets;
1237 0 : poDS->options = header.iOptions;
1238 0 : poDS->nFileSize = fileSize;
1239 :
1240 0 : poDS->nRasterXSize = header.iBlockWidth * header.iHorBlocks;
1241 0 : poDS->nRasterYSize = header.iBlockHeight * header.iVertBlocks;
1242 :
1243 0 : poDS->nBands = 1;
1244 :
1245 : GDALColorEntry oEntry;
1246 0 : poDS->poColorTable = new GDALColorTable();
1247 0 : for (GUInt16 i = 0; i < 256; i++)
1248 : {
1249 0 : oEntry.c1 = palette[i * 3 + 2]; // Red
1250 0 : oEntry.c2 = palette[i * 3 + 1]; // Green
1251 0 : oEntry.c3 = palette[i * 3]; // Blue
1252 0 : oEntry.c4 = 255;
1253 :
1254 0 : poDS->poColorTable->SetColorEntry(i, &oEntry);
1255 : }
1256 :
1257 : /* -------------------------------------------------------------------- */
1258 : /* Create band information objects. */
1259 : /* -------------------------------------------------------------------- */
1260 :
1261 0 : poDS->SetBand(1, new RIKRasterBand(poDS, 1));
1262 :
1263 : /* -------------------------------------------------------------------- */
1264 : /* Initialize any PAM information. */
1265 : /* -------------------------------------------------------------------- */
1266 :
1267 0 : poDS->SetDescription(poOpenInfo->pszFilename);
1268 0 : poDS->TryLoadXML();
1269 :
1270 : /* -------------------------------------------------------------------- */
1271 : /* Check for external overviews. */
1272 : /* -------------------------------------------------------------------- */
1273 0 : poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename,
1274 : poOpenInfo->GetSiblingFiles());
1275 :
1276 : /* -------------------------------------------------------------------- */
1277 : /* Confirm the requested access is supported. */
1278 : /* -------------------------------------------------------------------- */
1279 0 : if (poOpenInfo->eAccess == GA_Update)
1280 : {
1281 0 : delete poDS;
1282 0 : CPLError(CE_Failure, CPLE_NotSupported,
1283 : "The RIK driver does not support update access to existing"
1284 : " datasets.\n");
1285 0 : return nullptr;
1286 : }
1287 :
1288 0 : return poDS;
1289 : }
1290 :
1291 : /************************************************************************/
1292 : /* GDALRegister_RIK() */
1293 : /************************************************************************/
1294 :
1295 1511 : void GDALRegister_RIK()
1296 :
1297 : {
1298 1511 : if (GDALGetDriverByName("RIK") != nullptr)
1299 295 : return;
1300 :
1301 1216 : GDALDriver *poDriver = new GDALDriver();
1302 :
1303 1216 : poDriver->SetDescription("RIK");
1304 1216 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1305 1216 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Swedish Grid RIK (.rik)");
1306 1216 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rik.html");
1307 1216 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rik");
1308 1216 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1309 :
1310 1216 : poDriver->pfnOpen = RIKDataset::Open;
1311 1216 : poDriver->pfnIdentify = RIKDataset::Identify;
1312 :
1313 1216 : GetGDALDriverManager()->RegisterDriver(poDriver);
1314 : }
|