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