1 : /*****************************************************************************
2 : * $Id: IntergraphBand.cpp 25097 2012-10-11 17:36:10Z warmerdam $
3 : *
4 : * Project: Intergraph Raster Format support
5 : * Purpose: Read/Write Intergraph Raster Format, band support
6 : * Author: Ivan Lucena, ivan.lucena@pmldnet.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Ivan Lucena
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 "gdal_priv.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "cpl_csv.h"
34 : #include "ogr_spatialref.h"
35 : #include "gdal_pam.h"
36 : #include "gdal_alg.h"
37 : #include "math.h"
38 :
39 : #include "IntergraphDataset.h"
40 : #include "IntergraphBand.h"
41 : #include "IngrTypes.h"
42 :
43 : // ----------------------------------------------------------------------------
44 : // IntergraphRasterBand::IntergraphRasterBand()
45 : // ----------------------------------------------------------------------------
46 :
47 109 : IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
48 : int nBand,
49 : int nBandOffset,
50 109 : GDALDataType eType )
51 : {
52 109 : this->poColorTable = new GDALColorTable();
53 :
54 109 : this->poDS = poDS;
55 109 : this->nBand = nBand != 0 ? nBand : poDS->nBands;
56 109 : this->nTiles = 0;
57 109 : this->eDataType = eType;
58 109 : this->pabyBlockBuf = NULL;
59 109 : this->pahTiles = NULL;
60 109 : this->nRGBIndex = 0;
61 109 : this->nBandStart = nBandOffset;
62 109 : this->bTiled = FALSE;
63 :
64 : // --------------------------------------------------------------------
65 : // Get Header Info
66 : // --------------------------------------------------------------------
67 :
68 109 : memcpy(&hHeaderOne, &poDS->hHeaderOne, sizeof(hHeaderOne));
69 109 : memcpy(&hHeaderTwo, &poDS->hHeaderTwo, sizeof(hHeaderTwo));
70 :
71 : // --------------------------------------------------------------------
72 : // Get the image start from Words to Follow (WTF)
73 : // --------------------------------------------------------------------
74 :
75 109 : nDataOffset = nBandOffset + 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) );
76 :
77 : // --------------------------------------------------------------------
78 : // Get Color Tabel from Color Table Type (CTV)
79 : // --------------------------------------------------------------------
80 :
81 109 : uint32 nEntries = hHeaderTwo.NumberOfCTEntries;
82 :
83 109 : if( nEntries > 0 )
84 : {
85 5 : switch ( hHeaderTwo.ColorTableType )
86 : {
87 : case EnvironVColorTable:
88 5 : INGR_GetEnvironVColors( poDS->fp, nBandOffset, nEntries, poColorTable );
89 5 : if (poColorTable->GetColorEntryCount() == 0)
90 0 : return;
91 5 : break;
92 : case IGDSColorTable:
93 0 : INGR_GetIGDSColors( poDS->fp, nBandOffset, nEntries, poColorTable );
94 0 : if (poColorTable->GetColorEntryCount() == 0)
95 0 : return;
96 0 : break;
97 : default:
98 : CPLDebug( "INGR", "Wrong Color table type (%d), number of colors (%d)",
99 0 : hHeaderTwo.ColorTableType, nEntries );
100 : }
101 : }
102 :
103 : // --------------------------------------------------------------------
104 : // Set Dimension
105 : // --------------------------------------------------------------------
106 :
107 109 : nRasterXSize = hHeaderOne.PixelsPerLine;
108 109 : nRasterYSize = hHeaderOne.NumberOfLines;
109 :
110 109 : nBlockXSize = nRasterXSize;
111 109 : nBlockYSize = 1;
112 :
113 : // --------------------------------------------------------------------
114 : // Get tile directory
115 : // --------------------------------------------------------------------
116 :
117 109 : this->eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
118 :
119 109 : this->bTiled = (hHeaderOne.DataTypeCode == TiledRasterData);
120 :
121 109 : if( bTiled )
122 : {
123 : nTiles = INGR_GetTileDirectory( poDS->fp,
124 : nDataOffset,
125 : nRasterXSize,
126 : nRasterYSize,
127 : &hTileDir,
128 5 : &pahTiles );
129 5 : if (nTiles == 0)
130 0 : return;
131 :
132 5 : eFormat = (INGR_Format) hTileDir.DataTypeCode;
133 :
134 : // ----------------------------------------------------------------
135 : // Set blocks dimensions based on tiles
136 : // ----------------------------------------------------------------
137 5 : nBlockXSize = hTileDir.TileSize;
138 5 : nBlockYSize = hTileDir.TileSize;
139 : }
140 :
141 109 : if (nBlockXSize <= 0 || nBlockYSize <= 0)
142 : {
143 0 : pabyBlockBuf = NULL;
144 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid block dimensions");
145 0 : return;
146 : }
147 :
148 : // --------------------------------------------------------------------
149 : // Incomplete tiles have Block Offset greater than:
150 : // --------------------------------------------------------------------
151 :
152 109 : nFullBlocksX = ( nRasterXSize / nBlockXSize );
153 109 : nFullBlocksY = ( nRasterYSize / nBlockYSize );
154 :
155 : // --------------------------------------------------------------------
156 : // Get the Data Type from Format
157 : // --------------------------------------------------------------------
158 :
159 109 : this->eDataType = INGR_GetDataType( (uint16) eFormat );
160 :
161 : // --------------------------------------------------------------------
162 : // Allocate buffer for a Block of data
163 : // --------------------------------------------------------------------
164 :
165 : nBlockBufSize = nBlockXSize * nBlockYSize *
166 109 : GDALGetDataTypeSize( eDataType ) / 8;
167 :
168 : pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize, nBlockYSize,
169 109 : GDALGetDataTypeSize( eDataType ) / 8);
170 109 : if (pabyBlockBuf == NULL)
171 : {
172 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
173 0 : return;
174 : }
175 :
176 : // --------------------------------------------------------------------
177 : // More Metadata Information
178 : // --------------------------------------------------------------------
179 :
180 : SetMetadataItem( "FORMAT", INGR_GetFormatName( (uint16) eFormat ),
181 109 : "IMAGE_STRUCTURE" );
182 :
183 109 : if( bTiled )
184 : {
185 : SetMetadataItem( "TILESSIZE", CPLSPrintf ("%d", hTileDir.TileSize),
186 5 : "IMAGE_STRUCTURE" );
187 : }
188 : else
189 : {
190 104 : SetMetadataItem( "TILED", "NO", "IMAGE_STRUCTURE" );
191 : }
192 :
193 : SetMetadataItem( "ORIENTATION",
194 : INGR_GetOrientation( hHeaderOne.ScanlineOrientation ),
195 109 : "IMAGE_STRUCTURE" );
196 :
197 109 : if( eFormat == PackedBinary ||
198 : eFormat == RunLengthEncoded ||
199 : eFormat == CCITTGroup4 )
200 : {
201 3 : SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
202 : }
203 0 : }
204 :
205 : // ----------------------------------------------------------------------------
206 : // IntergraphRasterBand::~IntergraphRasterBand()
207 : // ----------------------------------------------------------------------------
208 :
209 109 : IntergraphRasterBand::~IntergraphRasterBand()
210 : {
211 109 : if( pabyBlockBuf )
212 : {
213 109 : CPLFree( pabyBlockBuf );
214 : }
215 :
216 109 : if( pahTiles )
217 : {
218 5 : CPLFree( pahTiles );
219 : }
220 :
221 109 : if( poColorTable )
222 : {
223 109 : delete poColorTable;
224 : }
225 109 : }
226 :
227 : // ----------------------------------------------------------------------------
228 : // IntergraphRasterBand::GetMinimum()
229 : // ----------------------------------------------------------------------------
230 :
231 0 : double IntergraphRasterBand::GetMinimum( int *pbSuccess )
232 : {
233 :
234 0 : double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum );
235 0 : double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum );
236 :
237 0 : if( pbSuccess )
238 : {
239 0 : *pbSuccess = dMinimum == dMaximum ? FALSE : TRUE;
240 : }
241 :
242 0 : return dMinimum;
243 : }
244 :
245 : // ----------------------------------------------------------------------------
246 : // IntergraphRasterBand::GetMaximum()
247 : // ----------------------------------------------------------------------------
248 :
249 0 : double IntergraphRasterBand::GetMaximum( int *pbSuccess )
250 : {
251 0 : double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum );
252 0 : double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum );
253 :
254 0 : if( pbSuccess )
255 : {
256 0 : *pbSuccess = dMinimum == dMaximum ? FALSE : TRUE;
257 : }
258 :
259 0 : return dMaximum;
260 : }
261 :
262 : // ----------------------------------------------------------------------------
263 : // IntergraphRasterBand::GetColorInterpretation()
264 : // ----------------------------------------------------------------------------
265 :
266 0 : GDALColorInterp IntergraphRasterBand::GetColorInterpretation()
267 : {
268 0 : if( eFormat == AdaptiveRGB ||
269 : eFormat == Uncompressed24bit ||
270 : eFormat == ContinuousTone )
271 : {
272 0 : switch( nRGBIndex )
273 : {
274 : case 1:
275 0 : return GCI_RedBand;
276 : case 2:
277 0 : return GCI_GreenBand;
278 : case 3:
279 0 : return GCI_BlueBand;
280 : }
281 0 : return GCI_GrayIndex;
282 : }
283 : else
284 : {
285 0 : if( poColorTable->GetColorEntryCount() > 0 )
286 : {
287 0 : return GCI_PaletteIndex;
288 : }
289 : else
290 : {
291 0 : return GCI_GrayIndex;
292 : }
293 : }
294 :
295 : }
296 :
297 : // ----------------------------------------------------------------------------
298 : // IntergraphRasterBand::GetColorTable()
299 : // ----------------------------------------------------------------------------
300 :
301 2 : GDALColorTable *IntergraphRasterBand::GetColorTable()
302 : {
303 2 : if( poColorTable->GetColorEntryCount() == 0 )
304 : {
305 1 : return NULL;
306 : }
307 : else
308 : {
309 1 : return poColorTable;
310 : }
311 : }
312 :
313 : // ----------------------------------------------------------------------------
314 : // IntergraphRasterBand::SetColorTable()
315 : // ----------------------------------------------------------------------------
316 :
317 19 : CPLErr IntergraphRasterBand::SetColorTable( GDALColorTable *poColorTable )
318 : {
319 19 : if( poColorTable == NULL )
320 : {
321 19 : return CE_None;
322 : }
323 :
324 0 : delete this->poColorTable;
325 0 : this->poColorTable = poColorTable->Clone();
326 :
327 0 : return CE_None;
328 : }
329 :
330 : // ----------------------------------------------------------------------------
331 : // IntergraphRasterBand::SetStatistics()
332 : // ----------------------------------------------------------------------------
333 :
334 20 : CPLErr IntergraphRasterBand::SetStatistics( double dfMin,
335 : double dfMax,
336 : double dfMean,
337 : double dfStdDev )
338 : {
339 20 : hHeaderOne.Minimum = INGR_SetMinMax( eDataType, dfMin );
340 20 : hHeaderOne.Maximum = INGR_SetMinMax( eDataType, dfMax );
341 :
342 20 : return GDALRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
343 : }
344 :
345 : // ----------------------------------------------------------------------------
346 : // IntergraphRasterBand::IReadBlock()
347 : // ----------------------------------------------------------------------------
348 :
349 1360 : CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
350 : int nBlockYOff,
351 : void *pImage )
352 : {
353 : // --------------------------------------------------------------------
354 : // Load Block Buffer
355 : // --------------------------------------------------------------------
356 1360 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
357 0 : return CE_None;
358 :
359 1360 : uint32 nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
360 :
361 1360 : if( nBytesRead == 0 )
362 : {
363 : memset( pImage, 0, nBlockXSize * nBlockYSize *
364 0 : GDALGetDataTypeSize( eDataType ) / 8 );
365 : CPLError( CE_Failure, CPLE_FileIO,
366 : "Can't read (%s) tile with X offset %d and Y offset %d.\n",
367 0 : ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff );
368 0 : return CE_Failure;
369 : }
370 :
371 : // --------------------------------------------------------------------
372 : // Reshape blocks if needed
373 : // --------------------------------------------------------------------
374 :
375 1360 : if( nBlockXOff == nFullBlocksX ||
376 : nBlockYOff == nFullBlocksY )
377 : {
378 0 : ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
379 : }
380 :
381 : // --------------------------------------------------------------------
382 : // Copy block buffer to image
383 : // --------------------------------------------------------------------
384 :
385 : memcpy( pImage, pabyBlockBuf, nBlockXSize * nBlockYSize *
386 1360 : GDALGetDataTypeSize( eDataType ) / 8 );
387 :
388 : #ifdef CPL_MSB
389 : if( eDataType == GDT_Int16 || eDataType == GDT_UInt16)
390 : GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize, 2 );
391 : else if( eDataType == GDT_Int32 || eDataType == GDT_UInt32 || eDataType == GDT_Float32 )
392 : GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
393 : else if (eDataType == GDT_Float64 )
394 : GDALSwapWords( pImage, 8, nBlockXSize * nBlockYSize, 8 );
395 : #endif
396 :
397 1360 : return CE_None;
398 : }
399 :
400 : // ----------------------------------------------------------------------------
401 : // IntergraphRasterBand::HandleUninstantiatedTile()
402 : // ----------------------------------------------------------------------------
403 :
404 1377 : int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
405 : int nBlockYOff,
406 : void* pImage)
407 : {
408 1377 : if( bTiled && pahTiles[nBlockXOff + nBlockYOff * nBlocksPerRow].Start == 0 )
409 : {
410 : // ------------------------------------------------------------
411 : // Uninstantieted tile, unique value
412 : // ------------------------------------------------------------
413 0 : int nColor = pahTiles[nBlockXOff + nBlockYOff * nBlocksPerRow].Used;
414 0 : switch( GetColorInterpretation() )
415 : {
416 : case GCI_RedBand:
417 0 : nColor >>= 16; break;
418 : case GCI_GreenBand:
419 0 : nColor >>= 8; break;
420 : default:
421 : break;
422 : }
423 : memset( pImage, nColor, nBlockXSize * nBlockYSize *
424 0 : GDALGetDataTypeSize( eDataType ) / 8 );
425 0 : return TRUE;
426 : }
427 : else
428 1377 : return FALSE;
429 : }
430 :
431 : // ----------------------------------------------------------------------------
432 : // IntergraphRGBBand::IntergraphRGBBand()
433 : // ----------------------------------------------------------------------------
434 :
435 18 : IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDS,
436 : int nBand,
437 : int nBandOffset,
438 : int nRGorB )
439 18 : : IntergraphRasterBand( poDS, nBand, nBandOffset )
440 : {
441 18 : if (pabyBlockBuf == NULL)
442 0 : return;
443 :
444 18 : nRGBIndex = (uint8) nRGorB;
445 :
446 : // --------------------------------------------------------------------
447 : // Reallocate buffer for a block of RGB Data
448 : // --------------------------------------------------------------------
449 :
450 18 : nBlockBufSize *= 3;
451 18 : CPLFree( pabyBlockBuf );
452 18 : pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
453 18 : if (pabyBlockBuf == NULL)
454 : {
455 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
456 : }
457 0 : }
458 :
459 : // ----------------------------------------------------------------------------
460 : // IntergraphRGBBand::IReadBlock()
461 : // ----------------------------------------------------------------------------
462 :
463 120 : CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
464 : int nBlockYOff,
465 : void *pImage )
466 : {
467 120 : if( IntergraphRasterBand::IReadBlock( nBlockXOff,
468 : nBlockYOff,
469 : pImage ) != CE_None )
470 : {
471 0 : return CE_Failure;
472 : }
473 :
474 : // --------------------------------------------------------------------
475 : // Extract the band of interest from the block buffer
476 : // --------------------------------------------------------------------
477 :
478 : int i, j;
479 :
480 15520 : for ( i = 0, j = ( nRGBIndex - 1 );
481 : i < ( nBlockXSize * nBlockYSize );
482 : i++, j += 3 )
483 : {
484 15400 : ( (GByte*) pImage )[i] = pabyBlockBuf[j];
485 : }
486 :
487 120 : return CE_None;
488 : }
489 :
490 : // ----------------------------------------------------------------------------
491 : // IntergraphRLEBand::IntergraphRLEBand()
492 : // ----------------------------------------------------------------------------
493 :
494 7 : IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
495 : int nBand,
496 : int nBandOffset,
497 : int nRGorB )
498 7 : : IntergraphRasterBand( poDS, nBand, nBandOffset )
499 : {
500 7 : nRLESize = 0;
501 7 : nRGBIndex = (uint8) nRGorB;
502 7 : bRLEBlockLoaded = FALSE;
503 7 : pabyRLEBlock = NULL;
504 7 : panRLELineOffset = NULL;
505 :
506 7 : if (pabyBlockBuf == NULL)
507 0 : return;
508 :
509 7 : if( ! this->bTiled )
510 : {
511 : // ------------------------------------------------------------
512 : // Load all rows at once
513 : // ------------------------------------------------------------
514 :
515 6 : nFullBlocksX = 1;
516 :
517 8 : if( eFormat == RunLengthEncodedC || eFormat == RunLengthEncoded )
518 : {
519 2 : nBlockYSize = 1;
520 : panRLELineOffset = (uint32 *)
521 2 : CPLCalloc(sizeof(uint32),nRasterYSize);
522 2 : nFullBlocksY = nRasterYSize;
523 : }
524 : else
525 : {
526 4 : nBlockYSize = nRasterYSize;
527 4 : nFullBlocksY = 1;
528 : }
529 :
530 : nRLESize = INGR_GetDataBlockSize( poDS->pszFilename,
531 : hHeaderTwo.CatenatedFilePointer,
532 6 : nDataOffset);
533 :
534 6 : nBlockBufSize = nBlockXSize * nBlockYSize;
535 : }
536 : else
537 : {
538 : // ------------------------------------------------------------
539 : // Find the biggest tile
540 : // ------------------------------------------------------------
541 :
542 : uint32 iTiles;
543 5 : for( iTiles = 0; iTiles < nTiles; iTiles++)
544 : {
545 4 : nRLESize = MAX( pahTiles[iTiles].Used, nRLESize );
546 : }
547 : }
548 :
549 : // ----------------------------------------------------------------
550 : // Realocate the decompressed Buffer
551 : // ----------------------------------------------------------------
552 :
553 7 : if( eFormat == AdaptiveRGB ||
554 : eFormat == ContinuousTone )
555 : {
556 3 : nBlockBufSize *= 3;
557 : }
558 :
559 7 : CPLFree( pabyBlockBuf );
560 7 : pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
561 7 : if (pabyBlockBuf == NULL)
562 : {
563 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
564 : }
565 :
566 : // ----------------------------------------------------------------
567 : // Create a RLE buffer
568 : // ----------------------------------------------------------------
569 :
570 7 : pabyRLEBlock = (GByte*) VSIMalloc( nRLESize );
571 7 : if (pabyRLEBlock == NULL)
572 : {
573 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nRLESize);
574 : }
575 :
576 : // ----------------------------------------------------------------
577 : // Set a black and white Color Table
578 : // ----------------------------------------------------------------
579 :
580 7 : if( eFormat == RunLengthEncoded )
581 : {
582 2 : BlackWhiteCT( true );
583 : }
584 :
585 0 : }
586 :
587 : // ----------------------------------------------------------------------------
588 : // IntergraphRLEBand::IntergraphRLEBand()
589 : // ----------------------------------------------------------------------------
590 :
591 7 : IntergraphRLEBand::~IntergraphRLEBand()
592 : {
593 7 : CPLFree( pabyRLEBlock );
594 7 : CPLFree( panRLELineOffset );
595 7 : }
596 :
597 : // ----------------------------------------------------------------------------
598 : // IntergraphRLEBand::IReadBlock()
599 : // ----------------------------------------------------------------------------
600 :
601 241 : CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
602 : int nBlockYOff,
603 : void *pImage )
604 : {
605 : // --------------------------------------------------------------------
606 : // Load Block Buffer
607 : // --------------------------------------------------------------------
608 :
609 : uint32 nBytesRead;
610 :
611 249 : if( bTiled || !bRLEBlockLoaded )
612 : {
613 8 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
614 0 : return CE_None;
615 :
616 8 : nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nRLESize, pabyRLEBlock );
617 8 : bRLEBlockLoaded = TRUE;
618 : }
619 : else
620 233 : nBytesRead = nRLESize;
621 :
622 241 : if( nBytesRead == 0 )
623 : {
624 : memset( pImage, 0, nBlockXSize * nBlockYSize *
625 0 : GDALGetDataTypeSize( eDataType ) / 8 );
626 : CPLError( CE_Failure, CPLE_FileIO,
627 : "Can't read (%s) tile with X offset %d and Y offset %d.\n%s",
628 : ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff,
629 0 : VSIStrerror( errno ) );
630 0 : return CE_Failure;
631 : }
632 :
633 : // ----------------------------------------------------------------
634 : // Calculate the resulting image dimmention
635 : // ----------------------------------------------------------------
636 :
637 241 : int nVirtualXSize = nBlockXSize;
638 241 : int nVirtualYSize = nBlockYSize;
639 :
640 241 : if( nBlockXOff == nFullBlocksX )
641 : {
642 2 : nVirtualXSize = nRasterXSize % nBlockXSize;
643 : }
644 :
645 241 : if( nBlockYOff == nFullBlocksY )
646 : {
647 2 : nVirtualYSize = nRasterYSize % nBlockYSize;
648 : }
649 :
650 : // --------------------------------------------------------------------
651 : // Decode Run Length
652 : // --------------------------------------------------------------------
653 :
654 245 : if( bTiled && eFormat == RunLengthEncoded )
655 : {
656 : nBytesRead =
657 : INGR_DecodeRunLengthBitonalTiled( pabyRLEBlock, pabyBlockBuf,
658 4 : nRLESize, nBlockBufSize, NULL );
659 : }
660 :
661 239 : else if( bTiled || panRLELineOffset == NULL )
662 : {
663 : nBytesRead = INGR_Decode( eFormat, pabyRLEBlock, pabyBlockBuf,
664 : nRLESize, nBlockBufSize,
665 2 : NULL );
666 : }
667 :
668 : else
669 : {
670 : // If we are missing the offset to this line, process all
671 : // preceding lines.
672 235 : if( nBlockYOff > 0 && panRLELineOffset[nBlockYOff] == 0 )
673 : {
674 : int iLine;
675 0 : for( iLine = 0; iLine < nBlockYOff; iLine++ )
676 0 : IReadBlock( 0, iLine, pImage );
677 : }
678 235 : if( nBlockYOff == 0 || panRLELineOffset[nBlockYOff] > 0 )
679 : {
680 : uint32 nBytesConsumed;
681 :
682 : nBytesRead =
683 : INGR_Decode( eFormat,
684 235 : pabyRLEBlock + panRLELineOffset[nBlockYOff],
685 : pabyBlockBuf, nRLESize, nBlockBufSize,
686 470 : &nBytesConsumed );
687 :
688 235 : if( nBlockYOff < nRasterYSize-1 )
689 233 : panRLELineOffset[nBlockYOff+1] =
690 233 : panRLELineOffset[nBlockYOff] + nBytesConsumed;
691 : }
692 : }
693 :
694 : // --------------------------------------------------------------------
695 : // Reshape blocks if needed
696 : // --------------------------------------------------------------------
697 :
698 241 : if( nBlockXOff == nFullBlocksX ||
699 : nBlockYOff == nFullBlocksY )
700 : {
701 3 : ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
702 : }
703 :
704 : // --------------------------------------------------------------------
705 : // Extract the band of interest from the block buffer (BIL)
706 : // --------------------------------------------------------------------
707 :
708 242 : if( eFormat == AdaptiveRGB ||
709 : eFormat == ContinuousTone )
710 : {
711 : int i, j;
712 1 : GByte *pabyImage = (GByte*) pImage;
713 1 : j = ( nRGBIndex - 1 ) * nVirtualXSize;
714 101 : for ( i = 0; i < nVirtualYSize; i++ )
715 : {
716 100 : memcpy( &pabyImage[i * nBlockXSize], &pabyBlockBuf[j], nBlockXSize );
717 100 : j += ( 3 * nBlockXSize );
718 : }
719 : }
720 : else
721 : {
722 240 : memcpy( pImage, pabyBlockBuf, nBlockBufSize );
723 : }
724 :
725 241 : return CE_None;
726 : }
727 :
728 : // ----------------------------------------------------------------------------
729 : // IntergraphBitmapBand::IntergraphBitmapBand()
730 : // ----------------------------------------------------------------------------
731 :
732 5 : IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDS,
733 : int nBand,
734 : int nBandOffset,
735 : int nRGorB )
736 5 : : IntergraphRasterBand( poDS, nBand, nBandOffset, GDT_Byte )
737 : {
738 5 : nBMPSize = 0;
739 5 : nRGBBand = nRGorB;
740 5 : pabyBMPBlock = NULL;
741 :
742 5 : if (pabyBlockBuf == NULL)
743 0 : return;
744 :
745 :
746 5 : if( ! this->bTiled )
747 : {
748 : // ------------------------------------------------------------
749 : // Load all rows at once
750 : // ------------------------------------------------------------
751 :
752 1 : nBlockYSize = nRasterYSize;
753 : nBMPSize = INGR_GetDataBlockSize( poDS->pszFilename,
754 : hHeaderTwo.CatenatedFilePointer,
755 1 : nDataOffset);
756 : }
757 : else
758 : {
759 : // ------------------------------------------------------------
760 : // Find the biggest tile
761 : // ------------------------------------------------------------
762 :
763 : uint32 iTiles;
764 20 : for( iTiles = 0; iTiles < nTiles; iTiles++)
765 : {
766 16 : nBMPSize = MAX( pahTiles[iTiles].Used, nBMPSize );
767 : }
768 : }
769 :
770 : // ----------------------------------------------------------------
771 : // Create a Bitmap buffer
772 : // ----------------------------------------------------------------
773 :
774 5 : pabyBMPBlock = (GByte*) VSIMalloc( nBMPSize );
775 5 : if (pabyBMPBlock == NULL)
776 : {
777 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBMPSize);
778 : }
779 :
780 : // ----------------------------------------------------------------
781 : // Set a black and white Color Table
782 : // ----------------------------------------------------------------
783 :
784 5 : if( eFormat == CCITTGroup4 )
785 : {
786 1 : BlackWhiteCT( true );
787 : }
788 :
789 : // ----------------------------------------------------------------
790 : // Read JPEG Quality from Application Data
791 : // ----------------------------------------------------------------
792 :
793 5 : if( eFormat == JPEGGRAY ||
794 : eFormat == JPEGRGB ||
795 : eFormat == JPEGCYMK )
796 : {
797 : nQuality = INGR_ReadJpegQuality( poDS->fp,
798 : hHeaderTwo.ApplicationPacketPointer,
799 4 : nDataOffset );
800 : }
801 0 : }
802 :
803 : // ----------------------------------------------------------------------------
804 : // IntergraphBitmapBand::~IntergraphBitmapBand()
805 : // ----------------------------------------------------------------------------
806 :
807 5 : IntergraphBitmapBand::~IntergraphBitmapBand()
808 : {
809 5 : CPLFree( pabyBMPBlock );
810 5 : }
811 :
812 : // ----------------------------------------------------------------------------
813 : // IntergraphBitmapBand::GetColorInterpretation()
814 : // ----------------------------------------------------------------------------
815 :
816 0 : GDALColorInterp IntergraphBitmapBand::GetColorInterpretation()
817 : {
818 0 : if( eFormat == JPEGRGB)
819 : {
820 0 : switch( nRGBBand )
821 : {
822 : case 1:
823 0 : return GCI_RedBand;
824 : case 2:
825 0 : return GCI_GreenBand;
826 : case 3:
827 0 : return GCI_BlueBand;
828 : }
829 0 : return GCI_GrayIndex;
830 : }
831 : else
832 : {
833 0 : if( poColorTable->GetColorEntryCount() > 0 )
834 : {
835 0 : return GCI_PaletteIndex;
836 : }
837 : else
838 : {
839 0 : return GCI_GrayIndex;
840 : }
841 : }
842 :
843 : }
844 :
845 : // ----------------------------------------------------------------------------
846 : // IntergraphBitmapBand::IReadBlock()
847 : // ----------------------------------------------------------------------------
848 :
849 9 : CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
850 : int nBlockYOff,
851 : void *pImage )
852 : {
853 9 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
854 :
855 : // ----------------------------------------------------------------
856 : // Load the block of a tile or a whole image
857 : // ----------------------------------------------------------------
858 9 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
859 0 : return CE_None;
860 :
861 9 : uint32 nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nBMPSize, pabyBMPBlock );
862 :
863 9 : if( nBytesRead == 0 )
864 : {
865 : memset( pImage, 0, nBlockXSize * nBlockYSize *
866 0 : GDALGetDataTypeSize( eDataType ) / 8 );
867 : CPLError( CE_Failure, CPLE_FileIO,
868 : "Can't read (%s) tile with X offset %d and Y offset %d.\n%s",
869 : ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff,
870 0 : VSIStrerror( errno ) );
871 0 : return CE_Failure;
872 : }
873 :
874 : // ----------------------------------------------------------------
875 : // Calculate the resulting image dimmention
876 : // ----------------------------------------------------------------
877 :
878 9 : int nVirtualXSize = nBlockXSize;
879 9 : int nVirtualYSize = nBlockYSize;
880 :
881 9 : if( nBlockXOff == nFullBlocksX )
882 : {
883 4 : nVirtualXSize = nRasterXSize % nBlockXSize;
884 : }
885 :
886 9 : if( nBlockYOff == nFullBlocksY )
887 : {
888 4 : nVirtualYSize = nRasterYSize % nBlockYSize;
889 : }
890 :
891 : // ----------------------------------------------------------------
892 : // Create an in memory small tiff file (~400K)
893 : // ----------------------------------------------------------------
894 :
895 : poGDS->hVirtual = INGR_CreateVirtualFile( poGDS->pszFilename,
896 : eFormat,
897 : nVirtualXSize,
898 : nVirtualYSize,
899 : hTileDir.TileSize,
900 : nQuality,
901 : pabyBMPBlock,
902 : nBytesRead,
903 9 : nRGBBand );
904 :
905 9 : if( poGDS->hVirtual.poDS == NULL )
906 : {
907 : memset( pImage, 0, nBlockXSize * nBlockYSize *
908 0 : GDALGetDataTypeSize( eDataType ) / 8 );
909 : CPLError( CE_Failure, CPLE_AppDefined,
910 : "Unable to open virtual file.\n"
911 0 : "Is the GTIFF and JPEG driver available?" );
912 0 : return CE_Failure;
913 : }
914 :
915 : // ----------------------------------------------------------------
916 : // Read the unique block from the in memory file and release it
917 : // ----------------------------------------------------------------
918 :
919 : poGDS->hVirtual.poBand->RasterIO( GF_Read, 0, 0,
920 : nVirtualXSize, nVirtualYSize, pImage,
921 9 : nVirtualXSize, nVirtualYSize, GDT_Byte, 0, 0 );
922 :
923 : // --------------------------------------------------------------------
924 : // Reshape blocks if needed
925 : // --------------------------------------------------------------------
926 :
927 9 : if( nBlockXOff == nFullBlocksX ||
928 : nBlockYOff == nFullBlocksY )
929 : {
930 6 : ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, (GByte*) pImage );
931 : }
932 :
933 9 : INGR_ReleaseVirtual( &poGDS->hVirtual );
934 :
935 9 : return CE_None;
936 : }
937 :
938 : // ----------------------------------------------------------------------------
939 : // IntergraphRasterBand::LoadBlockBuf()
940 : // ----------------------------------------------------------------------------
941 :
942 1377 : int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff,
943 : int nBlockYOff,
944 : int nBlobkBytes,
945 : GByte *pabyBlock )
946 : {
947 1377 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
948 :
949 1377 : uint32 nSeekOffset = 0;
950 1377 : uint32 nReadSize = 0;
951 1377 : uint32 nBlockId = 0;
952 :
953 : // --------------------------------------------------------------------
954 : // Read from tiles or read from strip
955 : // --------------------------------------------------------------------
956 :
957 1377 : if( bTiled )
958 : {
959 12 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
960 :
961 12 : if( pahTiles[nBlockId].Start == 0 )
962 : {
963 0 : return 0;
964 : }
965 :
966 12 : nSeekOffset = pahTiles[nBlockId].Start + nDataOffset;
967 12 : nReadSize = pahTiles[nBlockId].Used;
968 :
969 12 : if( (int) nReadSize > nBlobkBytes )
970 : {
971 : CPLDebug( "INGR",
972 : "LoadBlockBuf(%d,%d) - trimmed tile size from %d to %d.",
973 : nBlockXOff, nBlockYOff,
974 0 : (int) nReadSize, (int) nBlobkBytes );
975 0 : nReadSize = nBlobkBytes;
976 : }
977 : }
978 : else
979 : {
980 1365 : nSeekOffset = nDataOffset + ( nBlockBufSize * nBlockYOff );
981 1365 : nReadSize = nBlobkBytes;
982 : }
983 :
984 1377 : if( VSIFSeekL( poGDS->fp, nSeekOffset, SEEK_SET ) < 0 )
985 : {
986 0 : return 0;
987 : }
988 :
989 1377 : return VSIFReadL( pabyBlock, 1, nReadSize, poGDS->fp );
990 : }
991 :
992 : // ----------------------------------------------------------------------------
993 : // IntergraphRasterBand::ReshapeBlock()
994 : // ----------------------------------------------------------------------------
995 :
996 : /**
997 : * Complete Tile with zeroes to fill up a Block
998 : *
999 : * ### ##000 ###### ###00
1000 : * ### => ##000 , 000000 or ###00
1001 : * ##000 000000 00000
1002 : ***/
1003 :
1004 9 : void IntergraphRasterBand::ReshapeBlock( int nBlockXOff,
1005 : int nBlockYOff,
1006 : int nBlockBytes,
1007 : GByte *pabyBlock )
1008 : {
1009 9 : GByte *pabyTile = (GByte*) CPLCalloc( 1, nBlockBufSize );
1010 :
1011 9 : memcpy( pabyTile, pabyBlock, nBlockBytes );
1012 9 : memset( pabyBlock, 0, nBlockBytes );
1013 :
1014 9 : int nColSize = nBlockXSize;
1015 9 : int nRowSize = nBlockYSize;
1016 9 : int nCellBytes = GDALGetDataTypeSize( eDataType ) / 8;
1017 :
1018 9 : if( nBlockXOff + 1 == nBlocksPerRow )
1019 : {
1020 6 : nColSize = nRasterXSize % nBlockXSize;
1021 : }
1022 :
1023 9 : if( nBlockYOff + 1 == nBlocksPerColumn )
1024 : {
1025 6 : nRowSize = nRasterYSize % nBlockYSize;
1026 : }
1027 :
1028 9 : if( nRGBIndex > 0 )
1029 : {
1030 0 : nCellBytes = nCellBytes * 3;
1031 : }
1032 :
1033 495 : for( int iRow = 0; iRow < nRowSize; iRow++ )
1034 : {
1035 : memcpy( pabyBlock + ( iRow * nCellBytes * nBlockXSize ),
1036 : pabyTile + ( iRow * nCellBytes * nColSize ),
1037 486 : nCellBytes * nColSize);
1038 : }
1039 :
1040 9 : CPLFree( pabyTile );
1041 9 : }
1042 :
1043 : // ----------------------------------------------------------------------------
1044 : // IntergraphRasterBand::IWriteBlock()
1045 : // ----------------------------------------------------------------------------
1046 :
1047 660 : CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
1048 : int nBlockYOff,
1049 : void *pImage )
1050 : {
1051 660 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
1052 :
1053 660 : if( ( nBlockXOff == 0 ) && ( nBlockYOff == 0 ) )
1054 : {
1055 24 : FlushBandHeader();
1056 : }
1057 :
1058 660 : if( nRGBIndex > 0 )
1059 : {
1060 30 : if( nBand > 1 )
1061 : {
1062 20 : VSIFSeekL( poGDS->fp, nDataOffset + ( nBlockBufSize * nBlockYOff ), SEEK_SET );
1063 20 : VSIFReadL( pabyBlockBuf, 1, nBlockBufSize, poGDS->fp );
1064 : }
1065 : int i, j;
1066 330 : for( i = 0, j = ( 3 - nRGBIndex ); i < nBlockXSize; i++, j += 3 )
1067 : {
1068 300 : pabyBlockBuf[j] = ( ( GByte * ) pImage )[i];
1069 : }
1070 : }
1071 : else
1072 : {
1073 630 : memcpy( pabyBlockBuf, pImage, nBlockBufSize );
1074 : #ifdef CPL_MSB
1075 : if( eDataType == GDT_Int16 || eDataType == GDT_UInt16)
1076 : GDALSwapWords( pabyBlockBuf, 2, nBlockXSize * nBlockYSize, 2 );
1077 : else if( eDataType == GDT_Int32 || eDataType == GDT_UInt32 || eDataType == GDT_Float32 )
1078 : GDALSwapWords( pabyBlockBuf, 4, nBlockXSize * nBlockYSize, 4 );
1079 : else if (eDataType == GDT_Float64 )
1080 : GDALSwapWords( pabyBlockBuf, 8, nBlockXSize * nBlockYSize, 8 );
1081 : #endif
1082 : }
1083 :
1084 660 : VSIFSeekL( poGDS->fp, nDataOffset + ( nBlockBufSize * nBlockYOff ), SEEK_SET );
1085 :
1086 660 : if( ( uint32 ) VSIFWriteL( pabyBlockBuf, 1, nBlockBufSize, poGDS->fp ) < nBlockBufSize )
1087 : {
1088 : CPLError( CE_Failure, CPLE_FileIO,
1089 : "Can't write (%s) block with X offset %d and Y offset %d.\n%s",
1090 0 : poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
1091 0 : return CE_Failure;
1092 : }
1093 :
1094 660 : return CE_None;
1095 : }
1096 :
1097 : // ----------------------------------------------------------------------------
1098 : // IntergraphRasterBand::FlushBandHeader()
1099 : // ----------------------------------------------------------------------------
1100 :
1101 24 : void IntergraphRasterBand::FlushBandHeader( void )
1102 : {
1103 24 : if( nRGBIndex > 1 )
1104 : {
1105 2 : return;
1106 : }
1107 :
1108 22 : IntergraphDataset *poGDS = ( IntergraphDataset* ) poDS;
1109 :
1110 : INGR_ColorTable256 hCTab;
1111 :
1112 22 : if( poColorTable->GetColorEntryCount() > 0 )
1113 : {
1114 0 : hHeaderTwo.ColorTableType = IGDSColorTable;
1115 0 : hHeaderTwo.NumberOfCTEntries = poColorTable->GetColorEntryCount();
1116 0 : INGR_SetIGDSColors( poColorTable, &hCTab );
1117 : }
1118 :
1119 22 : if( nBand > poDS->GetRasterCount() )
1120 : {
1121 : hHeaderTwo.CatenatedFilePointer = nBand *
1122 0 : ( ( 3 * SIZEOF_HDR1 ) + ( nBlockBufSize * nRasterYSize ) );
1123 : }
1124 :
1125 22 : VSIFSeekL( poGDS->fp, nBandStart, SEEK_SET );
1126 :
1127 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)];
1128 :
1129 22 : INGR_HeaderOneMemToDisk( &hHeaderOne, abyBuf );
1130 :
1131 22 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR1, poGDS->fp );
1132 :
1133 22 : INGR_HeaderTwoAMemToDisk( &hHeaderTwo, abyBuf );
1134 :
1135 22 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, poGDS->fp );
1136 :
1137 22 : unsigned int i = 0;
1138 22 : unsigned int n = 0;
1139 :
1140 5654 : for( i = 0; i < 256; i++ )
1141 : {
1142 5632 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
1143 5632 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
1144 5632 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_blue );
1145 : }
1146 :
1147 22 : VSIFWriteL( abyBuf, 1, SIZEOF_CTAB, poGDS->fp );
1148 : }
1149 :
1150 : // ----------------------------------------------------------------------------
1151 : // IntergraphRasterBand::BlackWhiteCT()
1152 : // ----------------------------------------------------------------------------
1153 :
1154 3 : void IntergraphRasterBand::BlackWhiteCT( bool bReverse )
1155 : {
1156 : GDALColorEntry oBlack;
1157 : GDALColorEntry oWhite;
1158 :
1159 3 : oWhite.c1 = (short) 255;
1160 3 : oWhite.c2 = (short) 255;
1161 3 : oWhite.c3 = (short) 255;
1162 3 : oWhite.c4 = (short) 255;
1163 :
1164 3 : oBlack.c1 = (short) 0;
1165 3 : oBlack.c2 = (short) 0;
1166 3 : oBlack.c3 = (short) 0;
1167 3 : oBlack.c4 = (short) 255;
1168 :
1169 3 : if( bReverse )
1170 : {
1171 3 : poColorTable->SetColorEntry( 0, &oWhite );
1172 3 : poColorTable->SetColorEntry( 1, &oBlack );
1173 : }
1174 : else
1175 : {
1176 0 : poColorTable->SetColorEntry( 0, &oBlack );
1177 0 : poColorTable->SetColorEntry( 1, &oWhite );
1178 : }
1179 3 : }
|