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 218 : IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
48 : int nBand,
49 : int nBandOffset,
50 218 : GDALDataType eType )
51 : {
52 218 : this->poColorTable = new GDALColorTable();
53 :
54 218 : this->poDS = poDS;
55 218 : this->nBand = nBand != 0 ? nBand : poDS->nBands;
56 218 : this->nTiles = 0;
57 218 : this->eDataType = eType;
58 218 : this->pabyBlockBuf = NULL;
59 218 : this->pahTiles = NULL;
60 218 : this->nRGBIndex = 0;
61 218 : this->nBandStart = nBandOffset;
62 218 : this->bTiled = FALSE;
63 :
64 : // --------------------------------------------------------------------
65 : // Get Header Info
66 : // --------------------------------------------------------------------
67 :
68 218 : memcpy(&hHeaderOne, &poDS->hHeaderOne, sizeof(hHeaderOne));
69 218 : memcpy(&hHeaderTwo, &poDS->hHeaderTwo, sizeof(hHeaderTwo));
70 :
71 : // --------------------------------------------------------------------
72 : // Get the image start from Words to Follow (WTF)
73 : // --------------------------------------------------------------------
74 :
75 218 : nDataOffset = nBandOffset + 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) );
76 :
77 : // --------------------------------------------------------------------
78 : // Get Color Tabel from Color Table Type (CTV)
79 : // --------------------------------------------------------------------
80 :
81 218 : uint32 nEntries = hHeaderTwo.NumberOfCTEntries;
82 :
83 218 : if( nEntries > 0 )
84 : {
85 10 : switch ( hHeaderTwo.ColorTableType )
86 : {
87 : case EnvironVColorTable:
88 10 : INGR_GetEnvironVColors( poDS->fp, nBandOffset, nEntries, poColorTable );
89 10 : if (poColorTable->GetColorEntryCount() == 0)
90 0 : return;
91 10 : 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 218 : nRasterXSize = hHeaderOne.PixelsPerLine;
108 218 : nRasterYSize = hHeaderOne.NumberOfLines;
109 :
110 218 : nBlockXSize = nRasterXSize;
111 218 : nBlockYSize = 1;
112 :
113 : // --------------------------------------------------------------------
114 : // Get tile directory
115 : // --------------------------------------------------------------------
116 :
117 218 : this->eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
118 :
119 218 : this->bTiled = (hHeaderOne.DataTypeCode == TiledRasterData);
120 :
121 218 : if( bTiled )
122 : {
123 : nTiles = INGR_GetTileDirectory( poDS->fp,
124 : nDataOffset,
125 : nRasterXSize,
126 : nRasterYSize,
127 : &hTileDir,
128 10 : &pahTiles );
129 10 : if (nTiles == 0)
130 0 : return;
131 :
132 10 : eFormat = (INGR_Format) hTileDir.DataTypeCode;
133 :
134 : // ----------------------------------------------------------------
135 : // Set blocks dimensions based on tiles
136 : // ----------------------------------------------------------------
137 :
138 10 : nBlockXSize = MIN( hTileDir.TileSize, (uint32) nRasterXSize );
139 10 : nBlockYSize = MIN( hTileDir.TileSize, (uint32) nRasterYSize );
140 : }
141 :
142 218 : 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 218 : nFullBlocksX = ( nRasterXSize / nBlockXSize );
154 218 : nFullBlocksY = ( nRasterYSize / nBlockYSize );
155 :
156 : // --------------------------------------------------------------------
157 : // Get the Data Type from Format
158 : // --------------------------------------------------------------------
159 :
160 218 : this->eDataType = INGR_GetDataType( (uint16) eFormat );
161 :
162 : // --------------------------------------------------------------------
163 : // Allocate buffer for a Block of data
164 : // --------------------------------------------------------------------
165 :
166 : nBlockBufSize = nBlockXSize * nBlockYSize *
167 218 : GDALGetDataTypeSize( eDataType ) / 8;
168 :
169 : pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize, nBlockYSize,
170 218 : GDALGetDataTypeSize( eDataType ) / 8);
171 218 : 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 218 : "IMAGE_STRUCTURE" );
183 :
184 218 : if( bTiled )
185 : {
186 : SetMetadataItem( "TILESSIZE", CPLSPrintf ("%d", hTileDir.TileSize),
187 10 : "IMAGE_STRUCTURE" );
188 : }
189 : else
190 : {
191 208 : SetMetadataItem( "TILED", "NO", "IMAGE_STRUCTURE" );
192 : }
193 :
194 : SetMetadataItem( "ORIENTATION",
195 : INGR_GetOrientation( hHeaderOne.ScanlineOrientation ),
196 218 : "IMAGE_STRUCTURE" );
197 :
198 218 : if( eFormat == PackedBinary ||
199 : eFormat == RunLengthEncoded ||
200 : eFormat == CCITTGroup4 )
201 : {
202 6 : SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
203 : }
204 0 : }
205 :
206 : // ----------------------------------------------------------------------------
207 : // IntergraphRasterBand::~IntergraphRasterBand()
208 : // ----------------------------------------------------------------------------
209 :
210 218 : IntergraphRasterBand::~IntergraphRasterBand()
211 : {
212 218 : if( pabyBlockBuf )
213 : {
214 218 : CPLFree( pabyBlockBuf );
215 : }
216 :
217 218 : if( pahTiles )
218 : {
219 10 : CPLFree( pahTiles );
220 : }
221 :
222 218 : if( poColorTable )
223 : {
224 218 : delete poColorTable;
225 : }
226 218 : }
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 4 : GDALColorTable *IntergraphRasterBand::GetColorTable()
303 : {
304 4 : if( poColorTable->GetColorEntryCount() == 0 )
305 : {
306 2 : return NULL;
307 : }
308 : else
309 : {
310 2 : return poColorTable;
311 : }
312 : }
313 :
314 : // ----------------------------------------------------------------------------
315 : // IntergraphRasterBand::SetColorTable()
316 : // ----------------------------------------------------------------------------
317 :
318 38 : CPLErr IntergraphRasterBand::SetColorTable( GDALColorTable *poColorTable )
319 : {
320 38 : if( poColorTable == NULL )
321 : {
322 38 : 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 40 : CPLErr IntergraphRasterBand::SetStatistics( double dfMin,
336 : double dfMax,
337 : double dfMean,
338 : double dfStdDev )
339 : {
340 40 : hHeaderOne.Minimum = INGR_SetMinMax( eDataType, dfMin );
341 40 : hHeaderOne.Maximum = INGR_SetMinMax( eDataType, dfMax );
342 :
343 40 : return GDALRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
344 : }
345 :
346 : // ----------------------------------------------------------------------------
347 : // IntergraphRasterBand::IReadBlock()
348 : // ----------------------------------------------------------------------------
349 :
350 2720 : CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
351 : int nBlockYOff,
352 : void *pImage )
353 : {
354 : // --------------------------------------------------------------------
355 : // Load Block Buffer
356 : // --------------------------------------------------------------------
357 2720 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
358 0 : return CE_None;
359 :
360 2720 : uint32 nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
361 :
362 2720 : 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 2720 : 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 2720 : 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 2720 : return CE_None;
399 : }
400 :
401 : // ----------------------------------------------------------------------------
402 : // IntergraphRasterBand::HandleUninstantiatedTile()
403 : // ----------------------------------------------------------------------------
404 :
405 2754 : int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
406 : int nBlockYOff,
407 : void* pImage)
408 : {
409 2754 : 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 2754 : return FALSE;
430 : }
431 :
432 : // ----------------------------------------------------------------------------
433 : // IntergraphRGBBand::IntergraphRGBBand()
434 : // ----------------------------------------------------------------------------
435 :
436 36 : IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDS,
437 : int nBand,
438 : int nBandOffset,
439 : int nRGorB )
440 36 : : IntergraphRasterBand( poDS, nBand, nBandOffset )
441 : {
442 36 : if (pabyBlockBuf == NULL)
443 0 : return;
444 :
445 36 : nRGBIndex = (uint8) nRGorB;
446 :
447 : // --------------------------------------------------------------------
448 : // Reallocate buffer for a block of RGB Data
449 : // --------------------------------------------------------------------
450 :
451 36 : nBlockBufSize *= 3;
452 36 : CPLFree( pabyBlockBuf );
453 36 : pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
454 36 : 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 240 : CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
465 : int nBlockYOff,
466 : void *pImage )
467 : {
468 240 : 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 31040 : for ( i = 0, j = ( nRGBIndex - 1 );
482 : i < ( nBlockXSize * nBlockYSize );
483 : i++, j += 3 )
484 : {
485 30800 : ( (GByte*) pImage )[i] = pabyBlockBuf[j];
486 : }
487 :
488 240 : return CE_None;
489 : }
490 :
491 : // ----------------------------------------------------------------------------
492 : // IntergraphRLEBand::IntergraphRLEBand()
493 : // ----------------------------------------------------------------------------
494 :
495 14 : IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
496 : int nBand,
497 : int nBandOffset,
498 : int nRGorB )
499 14 : : IntergraphRasterBand( poDS, nBand, nBandOffset )
500 : {
501 14 : nRLESize = 0;
502 14 : nRGBIndex = (uint8) nRGorB;
503 14 : bRLEBlockLoaded = FALSE;
504 14 : pabyRLEBlock = NULL;
505 14 : panRLELineOffset = NULL;
506 :
507 14 : if (pabyBlockBuf == NULL)
508 0 : return;
509 :
510 14 : if( ! this->bTiled )
511 : {
512 : // ------------------------------------------------------------
513 : // Load all rows at once
514 : // ------------------------------------------------------------
515 :
516 12 : nFullBlocksX = 1;
517 :
518 16 : if( eFormat == RunLengthEncodedC || eFormat == RunLengthEncoded )
519 : {
520 4 : nBlockYSize = 1;
521 : panRLELineOffset = (uint32 *)
522 4 : CPLCalloc(sizeof(uint32),nRasterYSize);
523 4 : nFullBlocksY = nRasterYSize;
524 : }
525 : else
526 : {
527 8 : nBlockYSize = nRasterYSize;
528 8 : nFullBlocksY = 1;
529 : }
530 :
531 : nRLESize = INGR_GetDataBlockSize( poDS->pszFilename,
532 : hHeaderTwo.CatenatedFilePointer,
533 12 : nDataOffset);
534 :
535 12 : nBlockBufSize = nBlockXSize * nBlockYSize;
536 : }
537 : else
538 : {
539 : // ------------------------------------------------------------
540 : // Find the biggest tile
541 : // ------------------------------------------------------------
542 :
543 : uint32 iTiles;
544 10 : for( iTiles = 0; iTiles < nTiles; iTiles++)
545 : {
546 8 : nRLESize = MAX( pahTiles[iTiles].Used, nRLESize );
547 : }
548 : }
549 :
550 : // ----------------------------------------------------------------
551 : // Realocate the decompressed Buffer
552 : // ----------------------------------------------------------------
553 :
554 14 : if( eFormat == AdaptiveRGB ||
555 : eFormat == ContinuousTone )
556 : {
557 6 : nBlockBufSize *= 3;
558 : }
559 :
560 14 : CPLFree( pabyBlockBuf );
561 14 : pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
562 14 : 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 14 : pabyRLEBlock = (GByte*) VSIMalloc( nRLESize );
572 14 : 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 14 : if( eFormat == RunLengthEncoded )
582 : {
583 4 : BlackWhiteCT( true );
584 : }
585 :
586 0 : }
587 :
588 : // ----------------------------------------------------------------------------
589 : // IntergraphRLEBand::IntergraphRLEBand()
590 : // ----------------------------------------------------------------------------
591 :
592 14 : IntergraphRLEBand::~IntergraphRLEBand()
593 : {
594 14 : CPLFree( pabyRLEBlock );
595 14 : CPLFree( panRLELineOffset );
596 14 : }
597 :
598 : // ----------------------------------------------------------------------------
599 : // IntergraphRLEBand::IReadBlock()
600 : // ----------------------------------------------------------------------------
601 :
602 482 : CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
603 : int nBlockYOff,
604 : void *pImage )
605 : {
606 : // --------------------------------------------------------------------
607 : // Load Block Buffer
608 : // --------------------------------------------------------------------
609 :
610 : uint32 nBytesRead;
611 :
612 498 : if( bTiled || !bRLEBlockLoaded )
613 : {
614 16 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
615 0 : return CE_None;
616 :
617 16 : nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nRLESize, pabyRLEBlock );
618 16 : bRLEBlockLoaded = TRUE;
619 : }
620 : else
621 466 : nBytesRead = nRLESize;
622 :
623 482 : 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 482 : int nVirtualXSize = nBlockXSize;
639 482 : int nVirtualYSize = nBlockYSize;
640 :
641 482 : if( nBlockXOff == nFullBlocksX )
642 : {
643 4 : nVirtualXSize = nRasterXSize % nBlockXSize;
644 : }
645 :
646 482 : if( nBlockYOff == nFullBlocksY )
647 : {
648 4 : nVirtualYSize = nRasterYSize % nBlockYSize;
649 : }
650 :
651 : // --------------------------------------------------------------------
652 : // Decode Run Length
653 : // --------------------------------------------------------------------
654 :
655 490 : if( bTiled && eFormat == RunLengthEncoded )
656 : {
657 : nBytesRead =
658 : INGR_DecodeRunLengthBitonalTiled( pabyRLEBlock, pabyBlockBuf,
659 8 : nRLESize, nBlockBufSize, NULL );
660 : }
661 :
662 478 : else if( bTiled || panRLELineOffset == NULL )
663 : {
664 : nBytesRead = INGR_Decode( eFormat, pabyRLEBlock, pabyBlockBuf,
665 : nRLESize, nBlockBufSize,
666 4 : NULL );
667 : }
668 :
669 : else
670 : {
671 : // If we are missing the offset to this line, process all
672 : // preceding lines.
673 470 : 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 470 : if( nBlockYOff == 0 || panRLELineOffset[nBlockYOff] > 0 )
680 : {
681 : uint32 nBytesConsumed;
682 :
683 : nBytesRead =
684 : INGR_Decode( eFormat,
685 470 : pabyRLEBlock + panRLELineOffset[nBlockYOff],
686 : pabyBlockBuf, nRLESize, nBlockBufSize,
687 940 : &nBytesConsumed );
688 :
689 470 : if( nBlockYOff < nRasterYSize-1 )
690 466 : panRLELineOffset[nBlockYOff+1] =
691 466 : panRLELineOffset[nBlockYOff] + nBytesConsumed;
692 : }
693 : }
694 :
695 : // --------------------------------------------------------------------
696 : // Reshape blocks if needed
697 : // --------------------------------------------------------------------
698 :
699 482 : if( nBlockXOff == nFullBlocksX ||
700 : nBlockYOff == nFullBlocksY )
701 : {
702 6 : ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
703 : }
704 :
705 : // --------------------------------------------------------------------
706 : // Extract the band of interest from the block buffer (BIL)
707 : // --------------------------------------------------------------------
708 :
709 484 : if( eFormat == AdaptiveRGB ||
710 : eFormat == ContinuousTone )
711 : {
712 : int i, j;
713 2 : GByte *pabyImage = (GByte*) pImage;
714 2 : j = ( nRGBIndex - 1 ) * nVirtualXSize;
715 202 : for ( i = 0; i < nVirtualYSize; i++ )
716 : {
717 200 : memcpy( &pabyImage[i * nBlockXSize], &pabyBlockBuf[j], nBlockXSize );
718 200 : j += ( 3 * nBlockXSize );
719 : }
720 : }
721 : else
722 : {
723 480 : memcpy( pImage, pabyBlockBuf, nBlockBufSize );
724 : }
725 :
726 482 : return CE_None;
727 : }
728 :
729 : // ----------------------------------------------------------------------------
730 : // IntergraphBitmapBand::IntergraphBitmapBand()
731 : // ----------------------------------------------------------------------------
732 :
733 10 : IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDS,
734 : int nBand,
735 : int nBandOffset,
736 : int nRGorB )
737 10 : : IntergraphRasterBand( poDS, nBand, nBandOffset, GDT_Byte )
738 : {
739 10 : nBMPSize = 0;
740 10 : nRGBBand = nRGorB;
741 10 : pabyBMPBlock = NULL;
742 :
743 10 : if (pabyBlockBuf == NULL)
744 0 : return;
745 :
746 :
747 10 : if( ! this->bTiled )
748 : {
749 : // ------------------------------------------------------------
750 : // Load all rows at once
751 : // ------------------------------------------------------------
752 :
753 2 : nBlockYSize = nRasterYSize;
754 : nBMPSize = INGR_GetDataBlockSize( poDS->pszFilename,
755 : hHeaderTwo.CatenatedFilePointer,
756 2 : nDataOffset);
757 : }
758 : else
759 : {
760 : // ------------------------------------------------------------
761 : // Find the biggest tile
762 : // ------------------------------------------------------------
763 :
764 : uint32 iTiles;
765 40 : for( iTiles = 0; iTiles < nTiles; iTiles++)
766 : {
767 32 : nBMPSize = MAX( pahTiles[iTiles].Used, nBMPSize );
768 : }
769 : }
770 :
771 : // ----------------------------------------------------------------
772 : // Create a Bitmap buffer
773 : // ----------------------------------------------------------------
774 :
775 10 : pabyBMPBlock = (GByte*) VSIMalloc( nBMPSize );
776 10 : 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 10 : if( eFormat == CCITTGroup4 )
786 : {
787 2 : BlackWhiteCT( true );
788 : }
789 :
790 : // ----------------------------------------------------------------
791 : // Read JPEG Quality from Application Data
792 : // ----------------------------------------------------------------
793 :
794 10 : if( eFormat == JPEGGRAY ||
795 : eFormat == JPEGRGB ||
796 : eFormat == JPEGCYMK )
797 : {
798 : nQuality = INGR_ReadJpegQuality( poDS->fp,
799 : hHeaderTwo.ApplicationPacketPointer,
800 8 : nDataOffset );
801 : }
802 0 : }
803 :
804 : // ----------------------------------------------------------------------------
805 : // IntergraphBitmapBand::~IntergraphBitmapBand()
806 : // ----------------------------------------------------------------------------
807 :
808 10 : IntergraphBitmapBand::~IntergraphBitmapBand()
809 : {
810 10 : CPLFree( pabyBMPBlock );
811 10 : }
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 18 : CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
851 : int nBlockYOff,
852 : void *pImage )
853 : {
854 18 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
855 :
856 : // ----------------------------------------------------------------
857 : // Load the block of a tile or a whole image
858 : // ----------------------------------------------------------------
859 18 : if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
860 0 : return CE_None;
861 :
862 18 : uint32 nBytesRead = LoadBlockBuf( nBlockXOff, nBlockYOff, nBMPSize, pabyBMPBlock );
863 :
864 18 : 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 18 : int nVirtualXSize = nBlockXSize;
880 18 : int nVirtualYSize = nBlockYSize;
881 :
882 18 : if( nBlockXOff == nFullBlocksX )
883 : {
884 8 : nVirtualXSize = nRasterXSize % nBlockXSize;
885 : }
886 :
887 18 : if( nBlockYOff == nFullBlocksY )
888 : {
889 8 : 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 18 : nRGBBand );
905 :
906 18 : 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 18 : nVirtualXSize, nVirtualYSize, GDT_Byte, 0, 0 );
923 :
924 : // --------------------------------------------------------------------
925 : // Reshape blocks if needed
926 : // --------------------------------------------------------------------
927 :
928 18 : if( nBlockXOff == nFullBlocksX ||
929 : nBlockYOff == nFullBlocksY )
930 : {
931 12 : ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, (GByte*) pImage );
932 : }
933 :
934 18 : INGR_ReleaseVirtual( &poGDS->hVirtual );
935 :
936 18 : return CE_None;
937 : }
938 :
939 : // ----------------------------------------------------------------------------
940 : // IntergraphRasterBand::LoadBlockBuf()
941 : // ----------------------------------------------------------------------------
942 :
943 2754 : int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff,
944 : int nBlockYOff,
945 : int nBlobkBytes,
946 : GByte *pabyBlock )
947 : {
948 2754 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
949 :
950 2754 : uint32 nSeekOffset = 0;
951 2754 : uint32 nReadSize = 0;
952 2754 : uint32 nBlockId = 0;
953 :
954 : // --------------------------------------------------------------------
955 : // Read from tiles or read from strip
956 : // --------------------------------------------------------------------
957 :
958 2754 : if( bTiled )
959 : {
960 24 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
961 :
962 24 : if( pahTiles[nBlockId].Start == 0 )
963 : {
964 0 : return 0;
965 : }
966 :
967 24 : nSeekOffset = pahTiles[nBlockId].Start + nDataOffset;
968 24 : nReadSize = pahTiles[nBlockId].Used;
969 : }
970 : else
971 : {
972 2730 : nSeekOffset = nDataOffset + ( nBlockBufSize * nBlockYOff );
973 2730 : nReadSize = nBlobkBytes;
974 : }
975 :
976 2754 : if( VSIFSeekL( poGDS->fp, nSeekOffset, SEEK_SET ) < 0 )
977 : {
978 0 : return 0;
979 : }
980 :
981 2754 : 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 18 : void IntergraphRasterBand::ReshapeBlock( int nBlockXOff,
997 : int nBlockYOff,
998 : int nBlockBytes,
999 : GByte *pabyBlock )
1000 : {
1001 18 : GByte *pabyTile = (GByte*) CPLCalloc( 1, nBlockBufSize );
1002 :
1003 18 : memcpy( pabyTile, pabyBlock, nBlockBytes );
1004 18 : memset( pabyBlock, 0, nBlockBytes );
1005 :
1006 18 : int nColSize = nBlockXSize;
1007 18 : int nRowSize = nBlockYSize;
1008 18 : int nCellBytes = GDALGetDataTypeSize( eDataType ) / 8;
1009 :
1010 18 : if( nBlockXOff + 1 == nBlocksPerRow )
1011 : {
1012 12 : nColSize = nRasterXSize % nBlockXSize;
1013 : }
1014 :
1015 18 : if( nBlockYOff + 1 == nBlocksPerColumn )
1016 : {
1017 12 : nRowSize = nRasterYSize % nBlockYSize;
1018 : }
1019 :
1020 18 : if( nRGBIndex > 0 )
1021 : {
1022 0 : nCellBytes = nCellBytes * 3;
1023 : }
1024 :
1025 990 : for( int iRow = 0; iRow < nRowSize; iRow++ )
1026 : {
1027 : memcpy( pabyBlock + ( iRow * nCellBytes * nBlockXSize ),
1028 : pabyTile + ( iRow * nCellBytes * nColSize ),
1029 972 : nCellBytes * nColSize);
1030 : }
1031 :
1032 18 : CPLFree( pabyTile );
1033 18 : }
1034 :
1035 : // ----------------------------------------------------------------------------
1036 : // IntergraphRasterBand::IWriteBlock()
1037 : // ----------------------------------------------------------------------------
1038 :
1039 1320 : CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
1040 : int nBlockYOff,
1041 : void *pImage )
1042 : {
1043 1320 : IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
1044 :
1045 1320 : if( ( nBlockXOff == 0 ) && ( nBlockYOff == 0 ) )
1046 : {
1047 48 : FlushBandHeader();
1048 : }
1049 :
1050 1320 : if( nRGBIndex > 0 )
1051 : {
1052 60 : if( nBand > 1 )
1053 : {
1054 40 : VSIFSeekL( poGDS->fp, nDataOffset + ( nBlockBufSize * nBlockYOff ), SEEK_SET );
1055 40 : VSIFReadL( pabyBlockBuf, 1, nBlockBufSize, poGDS->fp );
1056 : }
1057 : int i, j;
1058 660 : for( i = 0, j = ( 3 - nRGBIndex ); i < nBlockXSize; i++, j += 3 )
1059 : {
1060 600 : pabyBlockBuf[j] = ( ( GByte * ) pImage )[i];
1061 : }
1062 : }
1063 : else
1064 : {
1065 1260 : 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 1320 : VSIFSeekL( poGDS->fp, nDataOffset + ( nBlockBufSize * nBlockYOff ), SEEK_SET );
1077 :
1078 1320 : 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 1320 : return CE_None;
1087 : }
1088 :
1089 : // ----------------------------------------------------------------------------
1090 : // IntergraphRasterBand::FlushBandHeader()
1091 : // ----------------------------------------------------------------------------
1092 :
1093 48 : void IntergraphRasterBand::FlushBandHeader( void )
1094 : {
1095 48 : if( nRGBIndex > 1 )
1096 : {
1097 4 : return;
1098 : }
1099 :
1100 44 : IntergraphDataset *poGDS = ( IntergraphDataset* ) poDS;
1101 :
1102 : INGR_ColorTable256 hCTab;
1103 :
1104 44 : 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 44 : if( nBand > poDS->GetRasterCount() )
1112 : {
1113 : hHeaderTwo.CatenatedFilePointer = nBand *
1114 0 : ( ( 3 * SIZEOF_HDR1 ) + ( nBlockBufSize * nRasterYSize ) );
1115 : }
1116 :
1117 44 : VSIFSeekL( poGDS->fp, nBandStart, SEEK_SET );
1118 :
1119 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)];
1120 :
1121 44 : INGR_HeaderOneMemToDisk( &hHeaderOne, abyBuf );
1122 :
1123 44 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR1, poGDS->fp );
1124 :
1125 44 : INGR_HeaderTwoAMemToDisk( &hHeaderTwo, abyBuf );
1126 :
1127 44 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, poGDS->fp );
1128 :
1129 44 : unsigned int i = 0;
1130 44 : unsigned int n = 0;
1131 :
1132 11308 : for( i = 0; i < 256; i++ )
1133 : {
1134 11264 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
1135 11264 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
1136 11264 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_blue );
1137 : }
1138 :
1139 44 : VSIFWriteL( abyBuf, 1, SIZEOF_CTAB, poGDS->fp );
1140 : }
1141 :
1142 : // ----------------------------------------------------------------------------
1143 : // IntergraphRasterBand::BlackWhiteCT()
1144 : // ----------------------------------------------------------------------------
1145 :
1146 6 : void IntergraphRasterBand::BlackWhiteCT( bool bReverse )
1147 : {
1148 : GDALColorEntry oBlack;
1149 : GDALColorEntry oWhite;
1150 :
1151 6 : oWhite.c1 = (short) 255;
1152 6 : oWhite.c2 = (short) 255;
1153 6 : oWhite.c3 = (short) 255;
1154 6 : oWhite.c4 = (short) 255;
1155 :
1156 6 : oBlack.c1 = (short) 0;
1157 6 : oBlack.c2 = (short) 0;
1158 6 : oBlack.c3 = (short) 0;
1159 6 : oBlack.c4 = (short) 255;
1160 :
1161 6 : if( bReverse )
1162 : {
1163 6 : poColorTable->SetColorEntry( 0, &oWhite );
1164 6 : poColorTable->SetColorEntry( 1, &oBlack );
1165 : }
1166 : else
1167 : {
1168 0 : poColorTable->SetColorEntry( 0, &oBlack );
1169 0 : poColorTable->SetColorEntry( 1, &oWhite );
1170 : }
1171 6 : }
|