1 : /******************************************************************************
2 : * $Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
3 : *
4 : * Project: FIT Driver
5 : * Purpose: Implement FIT Support - not using the SGI iflFIT library.
6 : * Author: Philip Nemec, nemec@keyholecorp.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, Keyhole, Inc.
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 "fit.h"
31 : #include "gstEndian.h"
32 : #include "gdal_pam.h"
33 : #include "cpl_string.h"
34 :
35 : CPL_CVSID("$Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
36 :
37 : CPL_C_START
38 :
39 : void GDALRegister_FIT(void);
40 : CPL_C_END
41 :
42 : #define FIT_WRITE
43 :
44 : #define FIT_PAGE_SIZE 128
45 :
46 : using namespace gstEndian;
47 :
48 : /************************************************************************/
49 : /* ==================================================================== */
50 : /* FITDataset */
51 : /* ==================================================================== */
52 : /************************************************************************/
53 :
54 : class FITRasterBand;
55 :
56 : class FITDataset : public GDALPamDataset
57 : {
58 : friend class FITRasterBand;
59 :
60 : VSILFILE *fp;
61 : FITinfo *info;
62 : double adfGeoTransform[6];
63 :
64 : public:
65 : FITDataset();
66 : ~FITDataset();
67 : static GDALDataset *Open( GDALOpenInfo * );
68 : // virtual CPLErr GetGeoTransform( double * );
69 : };
70 :
71 : #ifdef FIT_WRITE
72 : static GDALDataset *FITCreateCopy(const char * pszFilename,
73 : GDALDataset *poSrcDS,
74 : int bStrict, char ** papszOptions,
75 : GDALProgressFunc pfnProgress,
76 : void * pProgressData );
77 : #endif // FIT_WRITE
78 :
79 : /************************************************************************/
80 : /* ==================================================================== */
81 : /* FITRasterBand */
82 : /* ==================================================================== */
83 : /************************************************************************/
84 :
85 : class FITRasterBand : public GDALPamRasterBand
86 : {
87 : friend class FITDataset;
88 :
89 : unsigned long recordSize; // number of bytes of a single page/block/record
90 : unsigned long numXBlocks; // number of pages in the X direction
91 : unsigned long numYBlocks; // number of pages in the Y direction
92 : unsigned long bytesPerComponent;
93 : unsigned long bytesPerPixel;
94 : char *tmpImage;
95 :
96 : public:
97 :
98 : FITRasterBand( FITDataset *, int );
99 : ~FITRasterBand();
100 :
101 : // should override RasterIO eventually.
102 :
103 : virtual CPLErr IReadBlock( int, int, void * );
104 : // virtual CPLErr WriteBlock( int, int, void * );
105 : virtual double GetMinimum( int *pbSuccess );
106 : virtual double GetMaximum( int *pbSuccess );
107 : virtual GDALColorInterp GetColorInterpretation();
108 : };
109 :
110 :
111 : /************************************************************************/
112 : /* FITRasterBand() */
113 : /************************************************************************/
114 :
115 42 : FITRasterBand::FITRasterBand( FITDataset *poDS, int nBand ) : tmpImage( NULL )
116 :
117 : {
118 42 : this->poDS = poDS;
119 42 : this->nBand = nBand;
120 :
121 : /* -------------------------------------------------------------------- */
122 : /* Get the GDAL data type. */
123 : /* -------------------------------------------------------------------- */
124 42 : eDataType = fitDataType(poDS->info->dtype);
125 :
126 : /* -------------------------------------------------------------------- */
127 : /* Get the page sizes. */
128 : /* -------------------------------------------------------------------- */
129 42 : nBlockXSize = poDS->info->xPageSize;
130 42 : nBlockYSize = poDS->info->yPageSize;
131 :
132 : /* -------------------------------------------------------------------- */
133 : /* Caculate the values for record offset calculations. */
134 : /* -------------------------------------------------------------------- */
135 42 : bytesPerComponent = (GDALGetDataTypeSize(eDataType) / 8);
136 42 : bytesPerPixel = poDS->nBands * bytesPerComponent;
137 42 : recordSize = bytesPerPixel * nBlockXSize * nBlockYSize;
138 : numXBlocks =
139 42 : (unsigned long) ceil((double) poDS->info->xSize / nBlockXSize);
140 : numYBlocks =
141 42 : (unsigned long) ceil((double) poDS->info->ySize / nBlockYSize);
142 :
143 42 : tmpImage = (char *) malloc(recordSize);
144 42 : if (! tmpImage)
145 : CPLError(CE_Fatal, CPLE_NotSupported,
146 0 : "FITRasterBand couldn't allocate %lu bytes", recordSize);
147 :
148 : /* -------------------------------------------------------------------- */
149 : /* Set the access flag. For now we set it the same as the */
150 : /* whole dataset, but eventually this should take account of */
151 : /* locked channels, or read-only secondary data files. */
152 : /* -------------------------------------------------------------------- */
153 : /* ... */
154 42 : }
155 :
156 :
157 42 : FITRasterBand::~FITRasterBand()
158 : {
159 42 : if ( tmpImage )
160 42 : free ( tmpImage );
161 42 : }
162 :
163 :
164 : /************************************************************************/
165 : /* IReadBlock() */
166 : /************************************************************************/
167 :
168 : #define COPY_XFIRST(t) { \
169 : t *dstp = (t *) pImage; \
170 : t *srcp = (t *) tmpImage; \
171 : srcp += nBand-1; \
172 : long i = 0; \
173 : for(long y=ystart; y != ystop; y+= yinc) \
174 : for(long x=xstart; x != xstop; x+= xinc, i++) { \
175 : dstp[i] = srcp[(y * nBlockXSize + x) * \
176 : poFIT_DS->nBands]; \
177 : } \
178 : }
179 :
180 :
181 : #define COPY_YFIRST(t) { \
182 : t *dstp = (t *) pImage; \
183 : t *srcp = (t *) tmpImage; \
184 : srcp += nBand-1; \
185 : long i = 0; \
186 : for(long x=xstart; x != xstop; x+= xinc, i++) \
187 : for(long y=ystart; y != ystop; y+= yinc) { \
188 : dstp[i] = srcp[(x * nBlockYSize + y) * \
189 : poFIT_DS->nBands]; \
190 : } \
191 : }
192 :
193 700 : CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
194 : void * pImage )
195 :
196 : {
197 700 : FITDataset *poFIT_DS = (FITDataset *) poDS;
198 :
199 700 : uint64 tilenum = 0;
200 :
201 700 : switch (poFIT_DS->info->space) {
202 : case 1:
203 : // iflUpperLeftOrigin - from upper left corner
204 : // scan right then down
205 700 : tilenum = nBlockYOff * numXBlocks + nBlockXOff;
206 700 : break;
207 : case 2:
208 : // iflUpperRightOrigin - from upper right corner
209 : // scan left then down
210 0 : tilenum = numYBlocks * numXBlocks + (numXBlocks-1-nBlockXOff);
211 0 : break;
212 : case 3:
213 : // iflLowerRightOrigin - from lower right corner
214 : // scan left then up
215 : tilenum = (numYBlocks-1-nBlockYOff) * numXBlocks +
216 0 : (numXBlocks-1-nBlockXOff);
217 0 : break;
218 : case 4:
219 : // iflLowerLeftOrigin - from lower left corner
220 : // scan right then up
221 0 : tilenum = (numYBlocks-1-nBlockYOff) * numXBlocks + nBlockXOff;
222 0 : break;
223 : case 5:
224 : // iflLeftUpperOrigin -* from upper left corner
225 : // scan down then right
226 0 : tilenum = nBlockXOff * numYBlocks + nBlockYOff;
227 0 : break;
228 : case 6:
229 : // iflRightUpperOrigin - from upper right corner
230 : // scan down then left
231 0 : tilenum = (numXBlocks-1-nBlockXOff) * numYBlocks + nBlockYOff;
232 0 : break;
233 : case 7:
234 : // iflRightLowerOrigin - from lower right corner
235 : // scan up then left
236 0 : tilenum = nBlockXOff * numYBlocks + (numYBlocks-1-nBlockYOff);
237 0 : break;
238 : case 8:
239 : // iflLeftLowerOrigin -* from lower left corner
240 : // scan up then right
241 : tilenum = (numXBlocks-1-nBlockXOff) * numYBlocks +
242 0 : (numYBlocks-1-nBlockYOff);
243 0 : break;
244 : default:
245 : CPLError(CE_Failure, CPLE_NotSupported,
246 : "FIT - unrecognized image space %i",
247 0 : poFIT_DS->info->space);
248 0 : tilenum = 0;
249 : } // switch
250 :
251 700 : uint64 offset = poFIT_DS->info->dataOffset + recordSize * tilenum;
252 : // CPLDebug("FIT", "%i RasterBand::IReadBlock %i %i (out of %i %i) -- %i",
253 : // poFIT_DS->info->space,
254 : // nBlockXOff, nBlockYOff, numXBlocks, numYBlocks, tilenum);
255 :
256 700 : if ( VSIFSeekL( poFIT_DS->fp, offset, SEEK_SET ) == -1 ) {
257 : CPLError(CE_Failure, CPLE_NotSupported,
258 0 : "FIT - 64bit file seek failure, handle=%p", poFIT_DS->fp );
259 0 : return CE_Failure;
260 : }
261 :
262 : // XXX - should handle status
263 : // fast path is single component (ll?) - no copy needed
264 : char *p;
265 700 : int fastpath = FALSE;
266 :
267 700 : if ((poFIT_DS->nBands == 1) && (poFIT_DS->info->space == 1)) // upper left
268 700 : fastpath = TRUE;
269 :
270 700 : if (! fastpath) {
271 0 : VSIFReadL( tmpImage, recordSize, 1, poFIT_DS->fp );
272 : // offset to correct component to swap
273 0 : p = (char *) tmpImage + nBand-1;
274 : }
275 : else {
276 700 : VSIFReadL( pImage, recordSize, 1, poFIT_DS->fp );
277 700 : p = (char *) pImage;
278 : }
279 :
280 :
281 : #ifdef swapping
282 700 : unsigned long i = 0;
283 :
284 700 : switch(bytesPerComponent) {
285 : case 1:
286 : // do nothing
287 100 : break;
288 : case 2:
289 1000 : for(i=0; i < recordSize; i+= bytesPerPixel)
290 800 : gst_swap16(p + i);
291 200 : break;
292 : case 4:
293 1500 : for(i=0; i < recordSize; i+= bytesPerPixel)
294 1200 : gst_swap32(p + i);
295 300 : break;
296 : case 8:
297 500 : for(i=0; i < recordSize; i+= bytesPerPixel)
298 400 : gst_swap64(p + i);
299 100 : break;
300 : default:
301 : CPLError(CE_Failure, CPLE_NotSupported,
302 : "FITRasterBand::IReadBlock unsupported bytesPerPixel %lu",
303 0 : bytesPerComponent);
304 : } // switch
305 : #else
306 : (void) p; // avoid warnings.
307 : #endif // swapping
308 :
309 700 : if (! fastpath) {
310 : long xinc, yinc, xstart, ystart, xstop, ystop;
311 0 : if (poFIT_DS->info->space <= 4) {
312 : // scan left/right first
313 :
314 0 : switch (poFIT_DS->info->space) {
315 : case 1:
316 : // iflUpperLeftOrigin - from upper left corner
317 : // scan right then down
318 0 : xinc = 1;
319 0 : yinc = 1;
320 0 : break;
321 : case 2:
322 : // iflUpperRightOrigin - from upper right corner
323 : // scan left then down
324 0 : xinc = -1;
325 0 : yinc = 1;
326 0 : break;
327 : case 3:
328 : // iflLowerRightOrigin - from lower right corner
329 : // scan left then up
330 0 : xinc = -1;
331 0 : yinc = -1;
332 0 : break;
333 : case 4:
334 : // iflLowerLeftOrigin - from lower left corner
335 : // scan right then up
336 0 : xinc = 1;
337 0 : yinc = -1;
338 0 : break;
339 : default:
340 : CPLError(CE_Failure, CPLE_NotSupported,
341 : "FIT - unrecognized image space %i",
342 0 : poFIT_DS->info->space);
343 0 : xinc = 1;
344 0 : yinc = 1;
345 : } // switch
346 :
347 :
348 0 : if (xinc == 1) {
349 0 : xstart = 0;
350 0 : xstop = nBlockXSize;
351 : }
352 : else {
353 0 : xstart = nBlockXSize-1;
354 0 : xstop = -1;
355 : }
356 0 : if (yinc == 1) {
357 0 : ystart = 0;
358 0 : ystop = nBlockYSize;
359 : }
360 : else {
361 0 : int localBlockYSize = nBlockYSize;
362 : long maxy_full =
363 0 : (long) floor(poFIT_DS->info->ySize / (double) nBlockYSize);
364 0 : if (nBlockYOff >= maxy_full)
365 0 : localBlockYSize = poFIT_DS->info->ySize % nBlockYSize;
366 0 : ystart = localBlockYSize-1;
367 0 : ystop = -1;
368 : }
369 :
370 0 : switch(bytesPerComponent) {
371 : case 1:
372 0 : COPY_XFIRST(char);
373 0 : break;
374 : case 2:
375 0 : COPY_XFIRST(uint16);
376 0 : break;
377 : case 4:
378 0 : COPY_XFIRST(uint32);
379 0 : break;
380 : case 8:
381 0 : COPY_XFIRST(uint64);
382 0 : break;
383 : default:
384 : CPLError(CE_Failure, CPLE_NotSupported,
385 : "FITRasterBand::IReadBlock unsupported "
386 0 : "bytesPerComponent %lu", bytesPerComponent);
387 : } // switch
388 :
389 : } // scan left/right first
390 : else {
391 : // scan up/down first
392 :
393 0 : switch (poFIT_DS->info->space) {
394 : case 5:
395 : // iflLeftUpperOrigin -* from upper left corner
396 : // scan down then right
397 0 : xinc = 1;
398 0 : yinc = 1;
399 0 : break;
400 : case 6:
401 : // iflRightUpperOrigin - from upper right corner
402 : // scan down then left
403 0 : xinc = -1;
404 0 : yinc = 1;
405 0 : break;
406 : case 7:
407 : // iflRightLowerOrigin - from lower right corner
408 : // scan up then left
409 0 : xinc = -1;
410 0 : yinc = -1;
411 0 : break;
412 : case 8:
413 : // iflLeftLowerOrigin -* from lower left corner
414 : // scan up then right
415 0 : xinc = 1;
416 0 : yinc = -1;
417 0 : break;
418 : default:
419 : CPLError(CE_Failure, CPLE_NotSupported,
420 : "FIT - unrecognized image space %i",
421 0 : poFIT_DS->info->space);
422 0 : xinc = 1;
423 0 : yinc = 1;
424 : } // switch
425 :
426 0 : if (xinc == 1) {
427 0 : xstart = 0;
428 0 : xstop = nBlockXSize;
429 : }
430 : else {
431 0 : int localBlockXSize = nBlockXSize;
432 : long maxx_full =
433 0 : (long) floor(poFIT_DS->info->xSize / (double) nBlockXSize);
434 0 : if (nBlockXOff >= maxx_full)
435 0 : localBlockXSize = poFIT_DS->info->xSize % nBlockXSize;
436 0 : xstart = localBlockXSize-1;
437 0 : xstop = -1;
438 : }
439 0 : if (yinc == 1) {
440 0 : ystart = 0;
441 0 : ystop = nBlockYSize;
442 : }
443 : else {
444 0 : ystart = nBlockYSize-1;
445 0 : ystop = -1;
446 : }
447 :
448 0 : switch(bytesPerComponent) {
449 : case 1:
450 0 : COPY_YFIRST(char);
451 0 : break;
452 : case 2:
453 0 : COPY_YFIRST(uint16);
454 0 : break;
455 : case 4:
456 0 : COPY_YFIRST(uint32);
457 0 : break;
458 : case 8:
459 0 : COPY_YFIRST(uint64);
460 0 : break;
461 : default:
462 : CPLError(CE_Failure, CPLE_NotSupported,
463 : "FITRasterBand::IReadBlock unsupported "
464 0 : "bytesPerComponent %lu", bytesPerComponent);
465 : } // switch
466 :
467 : } // scan up/down first
468 :
469 : } // ! fastpath
470 700 : return CE_None;
471 : }
472 :
473 : #if 0
474 : /************************************************************************/
475 : /* ReadBlock() */
476 : /************************************************************************/
477 :
478 : CPLErr FITRasterBand::ReadBlock( int nBlockXOff, int nBlockYOff,
479 : void * pImage )
480 :
481 : {
482 : FITDataset *poFIT_DS = (FITDataset *) poDS;
483 :
484 :
485 :
486 : return CE_None;
487 : }
488 :
489 : /************************************************************************/
490 : /* WriteBlock() */
491 : /************************************************************************/
492 :
493 : CPLErr FITRasterBand::WriteBlock( int nBlockXOff, int nBlockYOff,
494 : void * pImage )
495 :
496 : {
497 : FITDataset *poFIT_DS = (FITDataset *) poDS;
498 :
499 :
500 :
501 : return CE_None;
502 : }
503 : #endif
504 :
505 : /************************************************************************/
506 : /* GetMinimum() */
507 : /************************************************************************/
508 :
509 0 : double FITRasterBand::GetMinimum( int *pbSuccess )
510 : {
511 0 : FITDataset *poFIT_DS = (FITDataset *) poDS;
512 :
513 0 : if ((! poFIT_DS) || (! poFIT_DS->info))
514 0 : return GDALRasterBand::GetMinimum( pbSuccess );
515 :
516 0 : if (pbSuccess)
517 0 : *pbSuccess = TRUE;
518 :
519 0 : if (poFIT_DS->info->version &&
520 : EQUALN((const char *) &(poFIT_DS->info->version), "02", 2)) {
521 0 : return poFIT_DS->info->minValue;
522 : }
523 : else {
524 0 : return GDALRasterBand::GetMinimum( pbSuccess );
525 : }
526 : }
527 :
528 : /************************************************************************/
529 : /* GetMaximum() */
530 : /************************************************************************/
531 :
532 0 : double FITRasterBand::GetMaximum( int *pbSuccess )
533 : {
534 0 : FITDataset *poFIT_DS = (FITDataset *) poDS;
535 :
536 0 : if ((! poFIT_DS) || (! poFIT_DS->info))
537 0 : return GDALRasterBand::GetMaximum( pbSuccess );
538 :
539 0 : if (pbSuccess)
540 0 : *pbSuccess = TRUE;
541 :
542 0 : if (EQUALN((const char *) &poFIT_DS->info->version, "02", 2)) {
543 0 : return poFIT_DS->info->maxValue;
544 : }
545 : else {
546 0 : return GDALRasterBand::GetMaximum( pbSuccess );
547 : }
548 : }
549 :
550 : /************************************************************************/
551 : /* GetColorInterpretation() */
552 : /************************************************************************/
553 :
554 23 : GDALColorInterp FITRasterBand::GetColorInterpretation()
555 : {
556 23 : FITDataset *poFIT_DS = (FITDataset *) poDS;
557 :
558 23 : if ((! poFIT_DS) || (! poFIT_DS->info))
559 0 : return GCI_Undefined;
560 :
561 23 : switch(poFIT_DS->info->cm) {
562 : case 1: // iflNegative - inverted luminance (min value is white)
563 : CPLError( CE_Warning, CPLE_NotSupported,
564 0 : "FIT - color model Negative not supported - ignoring model");
565 0 : return GCI_Undefined;
566 :
567 : case 2: // iflLuminance - luminance
568 14 : if (poFIT_DS->nBands != 1) {
569 : CPLError( CE_Failure, CPLE_NotSupported,
570 : "FIT - color model Luminance mismatch with %i bands",
571 0 : poFIT_DS->nBands);
572 0 : return GCI_Undefined;
573 : }
574 14 : switch (nBand) {
575 : case 1:
576 14 : return GCI_GrayIndex;
577 : default:
578 : CPLError( CE_Failure, CPLE_NotSupported,
579 0 : "FIT - color model Luminance unknown band %i", nBand);
580 0 : return GCI_Undefined;
581 : } // switch nBand
582 :
583 : case 3: // iflRGB - full color (Red, Green, Blue triplets)
584 3 : if (poFIT_DS->nBands != 3) {
585 : CPLError( CE_Failure, CPLE_NotSupported,
586 : "FIT - color model RGB mismatch with %i bands",
587 0 : poFIT_DS->nBands);
588 0 : return GCI_Undefined;
589 : }
590 3 : switch (nBand) {
591 : case 1:
592 1 : return GCI_RedBand;
593 : case 2:
594 1 : return GCI_GreenBand;
595 : case 3:
596 1 : return GCI_BlueBand;
597 : default:
598 : CPLError( CE_Failure, CPLE_NotSupported,
599 0 : "FIT - color model RGB unknown band %i", nBand);
600 0 : return GCI_Undefined;
601 : } // switch nBand
602 :
603 : case 4: // iflRGBPalette - color mapped values
604 : CPLError( CE_Warning, CPLE_NotSupported,
605 : "FIT - color model RGBPalette not supported - "
606 0 : "ignoring model");
607 0 : return GCI_Undefined;
608 :
609 : case 5: // iflRGBA - full color with transparency (alpha channel)
610 4 : if (poFIT_DS->nBands != 4) {
611 : CPLError( CE_Failure, CPLE_NotSupported,
612 : "FIT - color model RGBA mismatch with %i bands",
613 0 : poFIT_DS->nBands);
614 0 : return GCI_Undefined;
615 : }
616 4 : switch (nBand) {
617 : case 1:
618 1 : return GCI_RedBand;
619 : case 2:
620 1 : return GCI_GreenBand;
621 : case 3:
622 1 : return GCI_BlueBand;
623 : case 4:
624 1 : return GCI_AlphaBand;
625 : default:
626 : CPLError( CE_Failure, CPLE_NotSupported,
627 0 : "FIT - color model RGBA unknown band %i", nBand);
628 0 : return GCI_Undefined;
629 : } // switch nBand
630 :
631 : case 6: // iflHSV - Hue, Saturation, Value
632 0 : if (poFIT_DS->nBands != 3) {
633 : CPLError( CE_Failure, CPLE_NotSupported,
634 : "FIT - color model HSV mismatch with %i bands",
635 0 : poFIT_DS->nBands);
636 0 : return GCI_Undefined;
637 : }
638 0 : switch (nBand) {
639 : case 1:
640 0 : return GCI_HueBand;
641 : case 2:
642 0 : return GCI_SaturationBand;
643 : case 3:
644 0 : return GCI_LightnessBand;
645 : default:
646 : CPLError( CE_Failure, CPLE_NotSupported,
647 0 : "FIT - color model HSV unknown band %i", nBand);
648 0 : return GCI_Undefined;
649 : } // switch nBand
650 :
651 : case 7: // iflCMY - Cyan, Magenta, Yellow
652 0 : if (poFIT_DS->nBands != 3) {
653 : CPLError( CE_Failure, CPLE_NotSupported,
654 : "FIT - color model CMY mismatch with %i bands",
655 0 : poFIT_DS->nBands);
656 0 : return GCI_Undefined;
657 : }
658 0 : switch (nBand) {
659 : case 1:
660 0 : return GCI_CyanBand;
661 : case 2:
662 0 : return GCI_MagentaBand;
663 : case 3:
664 0 : return GCI_YellowBand;
665 : default:
666 : CPLError( CE_Failure, CPLE_NotSupported,
667 0 : "FIT - color model CMY unknown band %i", nBand);
668 0 : return GCI_Undefined;
669 : } // switch nBand
670 :
671 : case 8: // iflCMYK - Cyan, Magenta, Yellow, Black
672 0 : if (poFIT_DS->nBands != 4) {
673 : CPLError( CE_Failure, CPLE_NotSupported,
674 : "FIT - color model CMYK mismatch with %i bands",
675 0 : poFIT_DS->nBands);
676 0 : return GCI_Undefined;
677 : }
678 0 : switch (nBand) {
679 : case 1:
680 0 : return GCI_CyanBand;
681 : case 2:
682 0 : return GCI_MagentaBand;
683 : case 3:
684 0 : return GCI_YellowBand;
685 : case 4:
686 0 : return GCI_BlackBand;
687 : default:
688 : CPLError( CE_Failure, CPLE_NotSupported,
689 0 : "FIT - color model CMYK unknown band %i", nBand);
690 0 : return GCI_Undefined;
691 : } // switch nBand
692 :
693 : case 9: // iflBGR - full color (ordered Blue, Green, Red)
694 0 : if (poFIT_DS->nBands != 3) {
695 : CPLError( CE_Failure, CPLE_NotSupported,
696 : "FIT - color model BGR mismatch with %i bands",
697 0 : poFIT_DS->nBands);
698 0 : return GCI_Undefined;
699 : }
700 0 : switch (nBand) {
701 : case 1:
702 0 : return GCI_BlueBand;
703 : case 2:
704 0 : return GCI_GreenBand;
705 : case 3:
706 0 : return GCI_RedBand;
707 : default:
708 : CPLError( CE_Failure, CPLE_NotSupported,
709 0 : "FIT - color model BGR unknown band %i", nBand);
710 0 : return GCI_Undefined;
711 : } // switch nBand
712 :
713 : case 10: // iflABGR - Alpha, Blue, Green, Red (SGI frame buffers)
714 0 : if (poFIT_DS->nBands != 4) {
715 : CPLError( CE_Failure, CPLE_NotSupported,
716 : "FIT - color model ABGR mismatch with %i bands",
717 0 : poFIT_DS->nBands);
718 0 : return GCI_Undefined;
719 : }
720 0 : switch (nBand) {
721 : case 1:
722 0 : return GCI_AlphaBand;
723 : case 2:
724 0 : return GCI_BlueBand;
725 : case 3:
726 0 : return GCI_GreenBand;
727 : case 4:
728 0 : return GCI_RedBand;
729 : default:
730 : CPLError( CE_Failure, CPLE_NotSupported,
731 0 : "FIT - color model ABGR unknown band %i", nBand);
732 0 : return GCI_Undefined;
733 : } // switch nBand
734 :
735 : case 11: // iflMultiSpectral - multi-spectral data, arbitrary number of
736 : // chans
737 0 : return GCI_Undefined;
738 :
739 : case 12: // iflYCC PhotoCD color model (Luminance, Chrominance)
740 : CPLError( CE_Warning, CPLE_NotSupported,
741 0 : "FIT - color model YCC not supported - ignoring model");
742 0 : return GCI_Undefined;
743 :
744 : case 13: // iflLuminanceAlpha - Luminance plus alpha
745 1 : if (poFIT_DS->nBands != 2) {
746 : CPLError( CE_Failure, CPLE_NotSupported,
747 : "FIT - color model LuminanceAlpha mismatch with "
748 : "%i bands",
749 0 : poFIT_DS->nBands);
750 0 : return GCI_Undefined;
751 : }
752 1 : switch (nBand) {
753 : case 1:
754 1 : return GCI_GrayIndex;
755 : case 2:
756 0 : return GCI_AlphaBand;
757 : default:
758 : CPLError( CE_Failure, CPLE_NotSupported,
759 : "FIT - color model LuminanceAlpha unknown band %i",
760 0 : nBand);
761 0 : return GCI_Undefined;
762 : } // switch nBand
763 :
764 : default:
765 : CPLError( CE_Warning, CPLE_NotSupported,
766 : "FIT - unrecognized color model %i - ignoring model",
767 1 : poFIT_DS->info->cm);
768 1 : return GCI_Undefined;
769 : } // switch
770 : }
771 :
772 : /************************************************************************/
773 : /* FITDataset() */
774 : /************************************************************************/
775 :
776 32 : FITDataset::FITDataset() : fp( NULL ), info( NULL )
777 : {
778 :
779 32 : adfGeoTransform[0] = 0.0; // x origin (top left corner)
780 32 : adfGeoTransform[1] = 1.0; // x pixel size
781 32 : adfGeoTransform[2] = 0.0;
782 :
783 32 : adfGeoTransform[3] = 0.0; // y origin (top left corner)
784 32 : adfGeoTransform[4] = 0.0;
785 32 : adfGeoTransform[5] = 1.0; // y pixel size
786 32 : }
787 :
788 : /************************************************************************/
789 : /* ~FITDataset() */
790 : /************************************************************************/
791 :
792 32 : FITDataset::~FITDataset()
793 : {
794 32 : FlushCache();
795 32 : if (info)
796 32 : delete(info);
797 32 : if(fp)
798 32 : VSIFCloseL(fp);
799 32 : }
800 :
801 : // simple guard object to delete memory
802 : // when the guard goes out of scope
803 : template< class T >
804 : class DeleteGuard
805 : {
806 : public:
807 32 : DeleteGuard( T *p ) : _ptr( p ) { }
808 32 : ~DeleteGuard()
809 : {
810 32 : delete _ptr;
811 32 : }
812 :
813 32 : T *take()
814 : {
815 32 : T *tmp = _ptr;
816 32 : _ptr = 0;
817 32 : return tmp;
818 : }
819 :
820 : private:
821 : T *_ptr;
822 : // prevent default copy constructor and assignment operator
823 : DeleteGuard( const DeleteGuard & );
824 : DeleteGuard &operator=( const DeleteGuard & );
825 : };
826 :
827 : // simple guard object to free memory
828 : // when the guard goes out of scope
829 : template< class T >
830 : class FreeGuard
831 : {
832 : public:
833 40 : FreeGuard( T *p ) : _ptr( p ) { }
834 40 : ~FreeGuard()
835 : {
836 40 : if ( _ptr )
837 40 : free( _ptr );
838 40 : }
839 :
840 : T *take()
841 : {
842 : T *tmp = _ptr;
843 : _ptr = 0;
844 : return tmp;
845 : }
846 :
847 : private:
848 : T *_ptr;
849 : // prevent default copy constructor and assignment operator
850 : FreeGuard( const FreeGuard & );
851 : FreeGuard &operator=( const FreeGuard & );
852 : };
853 :
854 : /************************************************************************/
855 : /* Open() */
856 : /************************************************************************/
857 :
858 11435 : GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
859 : {
860 : /* -------------------------------------------------------------------- */
861 : /* First we check to see if the file has the expected header */
862 : /* bytes. */
863 : /* -------------------------------------------------------------------- */
864 :
865 11435 : if( poOpenInfo->nHeaderBytes < 5 )
866 10600 : return NULL;
867 :
868 :
869 835 : if( !EQUALN((const char *) poOpenInfo->pabyHeader, "IT01", 4) &&
870 : !EQUALN((const char *) poOpenInfo->pabyHeader, "IT02", 4) )
871 803 : return NULL;
872 :
873 32 : if( poOpenInfo->eAccess == GA_Update )
874 : {
875 : CPLError( CE_Failure, CPLE_NotSupported,
876 : "The FIT driver does not support update access to existing"
877 0 : " files.\n" );
878 0 : return NULL;
879 : }
880 :
881 : /* -------------------------------------------------------------------- */
882 : /* Create a corresponding GDALDataset. */
883 : /* -------------------------------------------------------------------- */
884 : FITDataset *poDS;
885 :
886 32 : poDS = new FITDataset();
887 32 : DeleteGuard<FITDataset> guard( poDS );
888 :
889 : // re-open file for large file (64bit) access
890 32 : if ( poOpenInfo->eAccess == GA_ReadOnly )
891 32 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
892 : else
893 0 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
894 :
895 32 : if ( !poDS->fp ) {
896 : CPLError( CE_Failure, CPLE_OpenFailed,
897 : "Failed to re-open %s with FIT driver.\n",
898 0 : poOpenInfo->pszFilename );
899 0 : return NULL;
900 : }
901 32 : poDS->eAccess = poOpenInfo->eAccess;
902 :
903 :
904 32 : poDS->info = new FITinfo;
905 32 : FITinfo *info = poDS->info;
906 :
907 : /* -------------------------------------------------------------------- */
908 : /* Read other header values. */
909 : /* -------------------------------------------------------------------- */
910 32 : FIThead02 *head = (FIThead02 *) poOpenInfo->pabyHeader;
911 :
912 : // extract the image attributes from the file header
913 32 : if (EQUALN((const char *) &head->version, "02", 2)) {
914 : // incomplete header
915 32 : if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead02) )
916 0 : return NULL;
917 :
918 32 : CPLDebug("FIT", "Loading file with header version 02");
919 :
920 32 : gst_swapb(head->minValue);
921 32 : info->minValue = head->minValue;
922 32 : gst_swapb(head->maxValue);
923 32 : info->maxValue = head->maxValue;
924 32 : gst_swapb(head->dataOffset);
925 32 : info->dataOffset = head->dataOffset;
926 :
927 32 : info->userOffset = sizeof(FIThead02);
928 : }
929 0 : else if (EQUALN((const char *) &head->version, "01", 2)) {
930 : // incomplete header
931 0 : if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead01) )
932 0 : return NULL;
933 :
934 0 : CPLDebug("FIT", "Loading file with header version 01");
935 :
936 : // map old style header into new header structure
937 0 : FIThead01* head01 = (FIThead01*)head;
938 0 : gst_swapb(head->dataOffset);
939 0 : info->dataOffset = head01->dataOffset;
940 :
941 0 : info->userOffset = sizeof(FIThead01);
942 : }
943 : else {
944 : // unrecognized header version
945 : CPLError( CE_Failure, CPLE_NotSupported,
946 : "FIT - unsupported header version %.2s\n",
947 0 : (const char*) &head->version);
948 0 : return NULL;
949 : }
950 :
951 : CPLDebug("FIT", "userOffset %i, dataOffset %i",
952 32 : info->userOffset, info->dataOffset);
953 :
954 32 : info->magic = head->magic;
955 32 : info->version = head->version;
956 :
957 32 : gst_swapb(head->xSize);
958 32 : info->xSize = head->xSize;
959 32 : gst_swapb(head->ySize);
960 32 : info->ySize = head->ySize;
961 32 : gst_swapb(head->zSize);
962 32 : info->zSize = head->zSize;
963 32 : gst_swapb(head->cSize);
964 32 : info->cSize = head->cSize;
965 32 : gst_swapb(head->dtype);
966 32 : info->dtype = head->dtype;
967 32 : gst_swapb(head->order);
968 32 : info->order = head->order;
969 32 : gst_swapb(head->space);
970 32 : info->space = head->space;
971 32 : gst_swapb(head->cm);
972 32 : info->cm = head->cm;
973 32 : gst_swapb(head->xPageSize);
974 32 : info->xPageSize = head->xPageSize;
975 32 : gst_swapb(head->yPageSize);
976 32 : info->yPageSize = head->yPageSize;
977 32 : gst_swapb(head->zPageSize);
978 32 : info->zPageSize = head->zPageSize;
979 32 : gst_swapb(head->cPageSize);
980 32 : info->cPageSize = head->cPageSize;
981 :
982 : CPLDebug("FIT", "size %i %i %i %i, pageSize %i %i %i %i",
983 : info->xSize, info->ySize, info->zSize, info->cSize,
984 : info->xPageSize, info->yPageSize, info->zPageSize,
985 32 : info->cPageSize);
986 :
987 : CPLDebug("FIT", "dtype %i order %i space %i cm %i",
988 32 : info->dtype, info->order, info->space, info->cm);
989 :
990 : /**************************/
991 :
992 32 : poDS->nRasterXSize = head->xSize;
993 32 : poDS->nRasterYSize = head->ySize;
994 32 : poDS->nBands = head->cSize;
995 :
996 : /* -------------------------------------------------------------------- */
997 : /* Check if 64 bit seek is needed. */
998 : /* -------------------------------------------------------------------- */
999 : uint64 bytesPerComponent =
1000 32 : (GDALGetDataTypeSize(fitDataType(poDS->info->dtype)) / 8);
1001 32 : uint64 bytesPerPixel = head->cSize * bytesPerComponent;
1002 : uint64 recordSize = bytesPerPixel * head->xPageSize *
1003 32 : head->yPageSize;
1004 : uint64 numXBlocks =
1005 32 : (uint64) ceil((double) head->xSize / head->xPageSize);
1006 : uint64 numYBlocks =
1007 32 : (uint64) ceil((double) head->ySize / head->yPageSize);
1008 :
1009 32 : uint64 maxseek = recordSize * numXBlocks * numYBlocks;
1010 :
1011 : // CPLDebug("FIT", "(sizeof %i) max seek %llx ==> %llx\n", sizeof(uint64),
1012 : // maxseek, maxseek >> 31);
1013 32 : if (maxseek >> 31) // signed long
1014 : #ifdef VSI_LARGE_API_SUPPORTED
1015 0 : CPLDebug("FIT", "Using 64 bit version of fseek");
1016 : #else
1017 : CPLError(CE_Fatal, CPLE_NotSupported,
1018 : "FIT - need 64 bit version of fseek");
1019 : #endif
1020 :
1021 : /* -------------------------------------------------------------------- */
1022 : /* Verify all "unused" header values. */
1023 : /* -------------------------------------------------------------------- */
1024 :
1025 32 : if( info->zSize != 1 )
1026 : {
1027 : CPLError( CE_Failure, CPLE_NotSupported,
1028 0 : "FIT driver - unsupported zSize %i\n", info->zSize);
1029 0 : return NULL;
1030 : }
1031 :
1032 32 : if( info->order != 1 ) // interleaved - RGBRGB
1033 : {
1034 : CPLError( CE_Failure, CPLE_NotSupported,
1035 0 : "FIT driver - unsupported order %i\n", info->order);
1036 0 : return NULL;
1037 : }
1038 :
1039 32 : if( info->zPageSize != 1 )
1040 : {
1041 : CPLError( CE_Failure, CPLE_NotSupported,
1042 0 : "FIT driver - unsupported zPageSize %i\n", info->zPageSize);
1043 0 : return NULL;
1044 : }
1045 :
1046 32 : if( info->cPageSize != info->cSize )
1047 : {
1048 : CPLError( CE_Failure, CPLE_NotSupported,
1049 : "FIT driver - unsupported cPageSize %i (!= %i)\n",
1050 0 : info->cPageSize, info->cSize);
1051 0 : return NULL;
1052 : }
1053 :
1054 : /* -------------------------------------------------------------------- */
1055 : /* Create band information objects. */
1056 : /* -------------------------------------------------------------------- */
1057 74 : for( int i = 0; i < poDS->nBands; i++ )
1058 : {
1059 42 : poDS->SetBand( i+1, new FITRasterBand( poDS, i+1 ) ) ;
1060 : }
1061 :
1062 : /* -------------------------------------------------------------------- */
1063 : /* Initialize any PAM information. */
1064 : /* -------------------------------------------------------------------- */
1065 32 : poDS->SetDescription( poOpenInfo->pszFilename );
1066 32 : poDS->TryLoadXML();
1067 :
1068 : /* -------------------------------------------------------------------- */
1069 : /* Check for external overviews. */
1070 : /* -------------------------------------------------------------------- */
1071 32 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
1072 :
1073 32 : return guard.take();
1074 : }
1075 :
1076 : /************************************************************************/
1077 : /* FITCreateCopy() */
1078 : /************************************************************************/
1079 :
1080 : #ifdef FIT_WRITE
1081 25 : static GDALDataset *FITCreateCopy(const char * pszFilename,
1082 : GDALDataset *poSrcDS,
1083 : int bStrict, char ** papszOptions,
1084 : GDALProgressFunc pfnProgress,
1085 : void * pProgressData )
1086 : {
1087 25 : CPLDebug("FIT", "CreateCopy %s - %i", pszFilename, bStrict);
1088 :
1089 25 : int nBands = poSrcDS->GetRasterCount();
1090 25 : if (nBands == 0)
1091 : {
1092 : CPLError( CE_Failure, CPLE_NotSupported,
1093 1 : "FIT driver does not support source dataset with zero band.\n");
1094 1 : return NULL;
1095 : }
1096 :
1097 : /* -------------------------------------------------------------------- */
1098 : /* Create the dataset. */
1099 : /* -------------------------------------------------------------------- */
1100 : VSILFILE *fpImage;
1101 :
1102 24 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
1103 : {
1104 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
1105 0 : return NULL;
1106 : }
1107 :
1108 24 : fpImage = VSIFOpenL( pszFilename, "wb" );
1109 24 : if( fpImage == NULL )
1110 : {
1111 : CPLError( CE_Failure, CPLE_OpenFailed,
1112 : "FIT - unable to create file %s.\n",
1113 2 : pszFilename );
1114 2 : return NULL;
1115 : }
1116 :
1117 : /* -------------------------------------------------------------------- */
1118 : /* Generate header. */
1119 : /* -------------------------------------------------------------------- */
1120 : // XXX - should FIT_PAGE_SIZE be based on file page size ??
1121 22 : int size = MAX(sizeof(FIThead02), FIT_PAGE_SIZE);
1122 22 : FIThead02 *head = (FIThead02 *) malloc(size);
1123 22 : FreeGuard<FIThead02> guardHead( head );
1124 :
1125 : // clean header so padding (past real header) is all zeros
1126 22 : memset( head, 0, size );
1127 :
1128 22 : strncpy((char *) &head->magic, "IT", 2);
1129 22 : strncpy((char *) &head->version, "02", 2);
1130 :
1131 22 : head->xSize = poSrcDS->GetRasterXSize();
1132 22 : gst_swapb(head->xSize);
1133 22 : head->ySize = poSrcDS->GetRasterYSize();
1134 22 : gst_swapb(head->ySize);
1135 22 : head->zSize = 1;
1136 22 : gst_swapb(head->zSize);
1137 :
1138 22 : head->cSize = nBands;
1139 22 : gst_swapb(head->cSize);
1140 :
1141 22 : GDALRasterBand *firstBand = poSrcDS->GetRasterBand(1);
1142 22 : if (! firstBand) {
1143 0 : VSIFCloseL(fpImage);
1144 0 : return NULL;
1145 : }
1146 :
1147 22 : head->dtype = fitGetDataType(firstBand->GetRasterDataType());
1148 22 : if (! head->dtype) {
1149 4 : VSIFCloseL(fpImage);
1150 4 : return NULL;
1151 : }
1152 18 : gst_swapb(head->dtype);
1153 18 : head->order = 1; // interleaved - RGBRGB
1154 18 : gst_swapb(head->order);
1155 18 : head->space = 1; // upper left
1156 18 : gst_swapb(head->space);
1157 :
1158 : // XXX - need to check all bands
1159 18 : head->cm = fitGetColorModel(firstBand->GetColorInterpretation(), nBands);
1160 18 : gst_swapb(head->cm);
1161 :
1162 : int blockX, blockY;
1163 18 : firstBand->GetBlockSize(&blockX, &blockY);
1164 18 : CPLDebug("FIT write", "inherited block size %ix%i", blockX, blockY);
1165 :
1166 18 : if( CSLFetchNameValue(papszOptions,"PAGESIZE") != NULL )
1167 : {
1168 7 : const char *str = CSLFetchNameValue(papszOptions,"PAGESIZE");
1169 : int newBlockX, newBlockY;
1170 7 : sscanf(str, "%i,%i", &newBlockX, &newBlockY);
1171 14 : if (newBlockX && newBlockY) {
1172 7 : blockX = newBlockX;
1173 7 : blockY = newBlockY;
1174 : }
1175 : else {
1176 : CPLError(CE_Failure, CPLE_OpenFailed,
1177 0 : "FIT - Unable to parse option PAGESIZE values [%s]", str);
1178 : }
1179 : }
1180 :
1181 : // XXX - need to do lots of checking of block size
1182 : // * provide ability to override block size with options
1183 : // * handle non-square block size (like scanline)
1184 : // - probably default from non-tiled image - have default block size
1185 : // * handle block size bigger than image size
1186 : // * undesirable block size (non power of 2, others?)
1187 : // * mismatched block sizes for different bands
1188 : // * image that isn't even pages (ie. partially empty pages at edge)
1189 18 : CPLDebug("FIT write", "using block size %ix%i", blockX, blockY);
1190 :
1191 18 : head->xPageSize = blockX;
1192 18 : gst_swapb(head->xPageSize);
1193 18 : head->yPageSize = blockY;
1194 18 : gst_swapb(head->yPageSize);
1195 18 : head->zPageSize = 1;
1196 18 : gst_swapb(head->zPageSize);
1197 18 : head->cPageSize = nBands;
1198 18 : gst_swapb(head->cPageSize);
1199 :
1200 : // XXX - need to check all bands
1201 18 : head->minValue = firstBand->GetMinimum();
1202 18 : gst_swapb(head->minValue);
1203 : // XXX - need to check all bands
1204 18 : head->maxValue = firstBand->GetMaximum();
1205 18 : gst_swapb(head->maxValue);
1206 18 : head->dataOffset = size;
1207 18 : gst_swapb(head->dataOffset);
1208 :
1209 18 : VSIFWriteL(head, size, 1, fpImage);
1210 :
1211 : /* -------------------------------------------------------------------- */
1212 : /* Loop over image, copying image data. */
1213 : /* -------------------------------------------------------------------- */
1214 : unsigned long bytesPerComponent =
1215 18 : (GDALGetDataTypeSize(firstBand->GetRasterDataType()) / 8);
1216 18 : unsigned long bytesPerPixel = nBands * bytesPerComponent;
1217 :
1218 18 : unsigned long pageBytes = blockX * blockY * bytesPerPixel;
1219 18 : char *output = (char *) malloc(pageBytes);
1220 18 : if (! output)
1221 : CPLError(CE_Fatal, CPLE_NotSupported,
1222 0 : "FITRasterBand couldn't allocate %lu bytes", pageBytes);
1223 18 : FreeGuard<char> guardOutput( output );
1224 :
1225 18 : long maxx = (long) ceil(poSrcDS->GetRasterXSize() / (double) blockX);
1226 18 : long maxy = (long) ceil(poSrcDS->GetRasterYSize() / (double) blockY);
1227 18 : long maxx_full = (long) floor(poSrcDS->GetRasterXSize() / (double) blockX);
1228 18 : long maxy_full = (long) floor(poSrcDS->GetRasterYSize() / (double) blockY);
1229 :
1230 18 : CPLDebug("FIT", "about to write %ld x %ld blocks", maxx, maxy);
1231 :
1232 99 : for(long y=0; y < maxy; y++)
1233 792 : for(long x=0; x < maxx; x++) {
1234 711 : long readX = blockX;
1235 711 : long readY = blockY;
1236 711 : int do_clean = FALSE;
1237 :
1238 : // handle cases where image size isn't an exact multiple
1239 : // of page size
1240 711 : if (x >= maxx_full) {
1241 0 : readX = poSrcDS->GetRasterXSize() % blockX;
1242 0 : do_clean = TRUE;
1243 : }
1244 711 : if (y >= maxy_full) {
1245 0 : readY = poSrcDS->GetRasterYSize() % blockY;
1246 0 : do_clean = TRUE;
1247 : }
1248 :
1249 : // clean out image if only doing partial reads
1250 711 : if (do_clean)
1251 0 : memset( output, 0, pageBytes );
1252 :
1253 1432 : for( int iBand = 0; iBand < nBands; iBand++ ) {
1254 721 : GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
1255 : CPLErr eErr =
1256 : poBand->RasterIO( GF_Read, // eRWFlag
1257 : x * blockX, // nXOff
1258 : y * blockY, // nYOff
1259 : readX, // nXSize
1260 : readY, // nYSize
1261 : output + iBand * bytesPerComponent,
1262 : // pData
1263 : blockX, // nBufXSize
1264 : blockY, // nBufYSize
1265 : firstBand->GetRasterDataType(),
1266 : // eBufType
1267 : bytesPerPixel, // nPixelSpace
1268 721 : bytesPerPixel * blockX); // nLineSpace
1269 721 : if (eErr != CE_None)
1270 : CPLError(CE_Failure, CPLE_FileIO,
1271 0 : "FIT write - CreateCopy got read error %i", eErr);
1272 : } // for iBand
1273 :
1274 : #ifdef swapping
1275 711 : char *p = output;
1276 : unsigned long i;
1277 711 : switch(bytesPerComponent) {
1278 : case 1:
1279 : // do nothing
1280 105 : break;
1281 : case 2:
1282 1202 : for(i=0; i < pageBytes; i+= bytesPerComponent)
1283 1000 : gst_swap16(p + i);
1284 202 : break;
1285 : case 4:
1286 1803 : for(i=0; i < pageBytes; i+= bytesPerComponent)
1287 1500 : gst_swap32(p + i);
1288 303 : break;
1289 : case 8:
1290 601 : for(i=0; i < pageBytes; i+= bytesPerComponent)
1291 500 : gst_swap64(p + i);
1292 101 : break;
1293 : default:
1294 : CPLError(CE_Failure, CPLE_NotSupported,
1295 : "FIT write - unsupported bytesPerPixel %lu",
1296 0 : bytesPerComponent);
1297 : } // switch
1298 : #endif // swapping
1299 :
1300 711 : VSIFWriteL(output, pageBytes, 1, fpImage);
1301 :
1302 711 : double perc = ((double) (y * maxx + x)) / (maxx * maxy);
1303 : // printf("progress %f\n", perc);
1304 711 : if( !pfnProgress( perc, NULL, pProgressData ) )
1305 : {
1306 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
1307 : //free(output);
1308 0 : VSIFCloseL( fpImage );
1309 0 : VSIUnlink( pszFilename );
1310 0 : return NULL;
1311 : }
1312 : } // for x
1313 :
1314 : //free(output);
1315 :
1316 18 : VSIFCloseL( fpImage );
1317 :
1318 18 : pfnProgress( 1.0, NULL, pProgressData );
1319 :
1320 : /* -------------------------------------------------------------------- */
1321 : /* Re-open dataset, and copy any auxilary pam information. */
1322 : /* -------------------------------------------------------------------- */
1323 : GDALPamDataset *poDS = (GDALPamDataset *)
1324 18 : GDALOpen( pszFilename, GA_ReadOnly );
1325 :
1326 18 : if( poDS )
1327 18 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
1328 :
1329 18 : return poDS;
1330 : }
1331 : #endif // FIT_WRITE
1332 :
1333 : /************************************************************************/
1334 : /* GetGeoTransform() */
1335 : /************************************************************************/
1336 :
1337 : // CPLErr FITDataset::GetGeoTransform( double * padfTransform )
1338 : // {
1339 : // CPLDebug("FIT", "FITDataset::GetGeoTransform");
1340 : // memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
1341 : // return( CE_None );
1342 : // }
1343 :
1344 : /************************************************************************/
1345 : /* GDALRegister_FIT() */
1346 : /************************************************************************/
1347 :
1348 558 : void GDALRegister_FIT()
1349 :
1350 : {
1351 : GDALDriver *poDriver;
1352 :
1353 558 : if( GDALGetDriverByName( "FIT" ) == NULL )
1354 : {
1355 537 : poDriver = new GDALDriver();
1356 :
1357 537 : poDriver->SetDescription( "FIT" );
1358 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1359 537 : "FIT Image" );
1360 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1361 537 : "frmt_various.html#" );
1362 537 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
1363 537 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1364 :
1365 537 : poDriver->pfnOpen = FITDataset::Open;
1366 : #ifdef FIT_WRITE
1367 537 : poDriver->pfnCreateCopy = FITCreateCopy;
1368 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1369 537 : "Byte UInt16 Int16 UInt32 Int32 Float32 Float64" );
1370 : #endif // FIT_WRITE
1371 :
1372 537 : GetGDALDriverManager()->RegisterDriver( poDriver );
1373 : }
1374 558 : }
|