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