ultimatepp/bazaar/plugin/gdal/frmts/sgi/sgidataset.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

833 lines
28 KiB
C++

/******************************************************************************
* $Id: sgidataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
*
* Project: SGI Image Driver
* Purpose: Implement SGI Image Support based on Paul Bourke's SGI Image code.
* http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/
* ftp://ftp.sgi.com/graphics/SGIIMAGESPEC
* Authors: Mike Mazzella (GDAL driver)
* Paul Bourke (original SGI format code)
* Frank Warmerdam (write support)
*
******************************************************************************
* Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
* Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "gdal_pam.h"
#include "cpl_port.h"
#include "cpl_string.h"
CPL_CVSID("$Id: sgidataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
CPL_C_START
void GDALRegister_SGI(void);
CPL_C_END
struct ImageRec
{
GUInt16 imagic;
GByte type;
GByte bpc;
GUInt16 dim;
GUInt16 xsize;
GUInt16 ysize;
GUInt16 zsize;
GUInt32 min;
GUInt32 max;
char wasteBytes[4];
char name[80];
GUInt32 colorMap;
VSILFILE* file;
std::string fileName;
unsigned char* tmp;
GUInt32 rleEnd;
int rleTableDirty;
GUInt32* rowStart;
GInt32* rowSize;
ImageRec()
: imagic(0),
type(0),
bpc(1),
dim(0),
xsize(0),
ysize(0),
zsize(0),
min(0),
max(0),
colorMap(0),
file(NULL),
fileName(""),
tmp(NULL),
rleEnd(0),
rleTableDirty(FALSE),
rowStart(NULL),
rowSize(NULL)
{
memset(wasteBytes, 0, 4);
memset(name, 0, 80);
}
void Swap()
{
#ifdef CPL_LSB
CPL_SWAP16PTR(&imagic);
CPL_SWAP16PTR(&dim);
CPL_SWAP16PTR(&xsize);
CPL_SWAP16PTR(&ysize);
CPL_SWAP16PTR(&zsize);
CPL_SWAP32PTR(&min);
CPL_SWAP32PTR(&max);
#endif
}
};
/************************************************************************/
/* ConvertLong() */
/************************************************************************/
static void ConvertLong(GUInt32* array, GInt32 length)
{
#ifdef CPL_LSB
GUInt32* ptr;
ptr = (GUInt32*)array;
while(length--)
CPL_SWAP32PTR(ptr++);
#endif
}
/************************************************************************/
/* ImageGetRow() */
/************************************************************************/
static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z)
{
unsigned char *iPtr, *oPtr, pixel;
int count;
y = image->ysize - 1 - y;
if(int(image->type) == 1)
{
// reads row
VSIFSeekL(image->file, (long)image->rowStart[y+z*image->ysize], SEEK_SET);
if(VSIFReadL(image->tmp, 1, (GUInt32)image->rowSize[y+z*image->ysize], image->file) != (GUInt32)image->rowSize[y+z*image->ysize])
{
CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
return CE_Failure;
}
// expands row
iPtr = image->tmp;
oPtr = buf;
int xsizeCount = 0;
for(;;)
{
pixel = *iPtr++;
count = (int)(pixel & 0x7F);
if(!count)
{
if(xsizeCount != image->xsize)
{
CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
return CE_Failure;
}
else
{
return CE_None;
}
}
if( xsizeCount + count > image->xsize )
{
CPLError(CE_Failure, CPLE_AppDefined, "Wrong repetition number that would overflow data at line %d", y);
return CE_Failure;
}
if(pixel & 0x80)
{
memcpy(oPtr, iPtr, count);
iPtr += count;
}
else
{
pixel = *iPtr++;
memset(oPtr, pixel, count);
}
oPtr += count;
xsizeCount += count;
}
}
else
{
VSIFSeekL(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), SEEK_SET);
if(VSIFReadL(buf, 1, image->xsize, image->file) != image->xsize)
{
CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
return CE_Failure;
}
}
return CE_None;
}
/************************************************************************/
/* ==================================================================== */
/* SGIDataset */
/* ==================================================================== */
/************************************************************************/
class SGIRasterBand;
class SGIDataset : public GDALPamDataset
{
friend class SGIRasterBand;
VSILFILE* fpImage;
int bGeoTransformValid;
double adfGeoTransform[6];
ImageRec image;
public:
SGIDataset();
~SGIDataset();
virtual CPLErr GetGeoTransform(double*);
static GDALDataset* Open(GDALOpenInfo*);
static GDALDataset *Create( const char * pszFilename,
int nXSize, int nYSize, int nBands,
GDALDataType eType, char **papszOptions );
};
/************************************************************************/
/* ==================================================================== */
/* SGIRasterBand */
/* ==================================================================== */
/************************************************************************/
class SGIRasterBand : public GDALPamRasterBand
{
friend class SGIDataset;
public:
SGIRasterBand(SGIDataset*, int);
virtual CPLErr IReadBlock(int, int, void*);
virtual CPLErr IWriteBlock(int, int, void*);
virtual GDALColorInterp GetColorInterpretation();
};
/************************************************************************/
/* SGIRasterBand() */
/************************************************************************/
SGIRasterBand::SGIRasterBand(SGIDataset* poDS, int nBand)
{
this->poDS = poDS;
this->nBand = nBand;
if(poDS == NULL)
{
eDataType = GDT_Byte;
}
else
{
if(int(poDS->image.bpc) == 1)
eDataType = GDT_Byte;
else
eDataType = GDT_Int16;
}
nBlockXSize = poDS->nRasterXSize;;
nBlockYSize = 1;
}
/************************************************************************/
/* IReadBlock() */
/************************************************************************/
CPLErr SGIRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
int nBlockYOff,
void* pImage)
{
SGIDataset* poGDS = (SGIDataset*) poDS;
CPLAssert(nBlockXOff == 0);
/* -------------------------------------------------------------------- */
/* Load the desired data into the working buffer. */
/* -------------------------------------------------------------------- */
return ImageGetRow(&(poGDS->image), (unsigned char*)pImage, nBlockYOff, nBand-1);
}
/************************************************************************/
/* IWritelock() */
/************************************************************************/
CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
int nBlockYOff,
void* pImage)
{
SGIDataset* poGDS = (SGIDataset*) poDS;
ImageRec *image = &(poGDS->image);
CPLAssert(nBlockXOff == 0);
/* -------------------------------------------------------------------- */
/* Handle the fairly trivial non-RLE case. */
/* -------------------------------------------------------------------- */
if( image->type == 0 )
{
VSIFSeekL(image->file,
512 + (nBlockYOff*image->xsize)
+ ((nBand-1)*image->xsize*image->ysize ),
SEEK_SET);
if(VSIFWriteL(pImage, 1, image->xsize, image->file) != image->xsize)
{
CPLError(CE_Failure, CPLE_OpenFailed,
"file write error: row (%d)\n", nBlockYOff );
return CE_Failure;
}
return CE_None;
}
/* -------------------------------------------------------------------- */
/* Handle RLE case. */
/* -------------------------------------------------------------------- */
const GByte *pabyRawBuf = (const GByte *) pImage;
GByte *pabyRLEBuf = (GByte *) CPLMalloc(image->xsize * 2 + 6);
int iX = 0, nRLEBytes = 0;
while( iX < image->xsize )
{
int nRepeatCount = 1;
while( iX + nRepeatCount < image->xsize
&& nRepeatCount < 127
&& pabyRawBuf[iX + nRepeatCount] == pabyRawBuf[iX] )
nRepeatCount++;
if( nRepeatCount > 2
|| iX + nRepeatCount == image->xsize
|| (iX + nRepeatCount < image->xsize - 2
&& pabyRawBuf[iX + nRepeatCount + 1]
== pabyRawBuf[iX + nRepeatCount + 2]
&& pabyRawBuf[iX + nRepeatCount + 1]
== pabyRawBuf[iX + nRepeatCount + 3]) )
{ // encode a constant run.
pabyRLEBuf[nRLEBytes++] = (GByte) nRepeatCount;
pabyRLEBuf[nRLEBytes++] = pabyRawBuf[iX];
iX += nRepeatCount;
}
else
{ // copy over mixed data.
nRepeatCount = 1;
for( nRepeatCount = 1;
iX + nRepeatCount < image->xsize && nRepeatCount < 127;
nRepeatCount++ )
{
if( iX + nRepeatCount + 3 >= image->xsize )
continue;
// quit if the next 3 pixels match
if( pabyRawBuf[iX + nRepeatCount]
== pabyRawBuf[iX + nRepeatCount+1]
&& pabyRawBuf[iX + nRepeatCount]
== pabyRawBuf[iX + nRepeatCount+2] )
break;
}
pabyRLEBuf[nRLEBytes++] = (GByte) (0x80 | nRepeatCount);
memcpy( pabyRLEBuf + nRLEBytes,
pabyRawBuf + iX,
nRepeatCount );
nRLEBytes += nRepeatCount;
iX += nRepeatCount;
}
}
// EOL marker.
pabyRLEBuf[nRLEBytes++] = 0;
/* -------------------------------------------------------------------- */
/* Write RLE Buffer at end of file. */
/* -------------------------------------------------------------------- */
int row = (image->ysize - nBlockYOff - 1) + (nBand-1) * image->ysize;
VSIFSeekL(image->file, 0, SEEK_END );
image->rowStart[row] = (GUInt32) VSIFTellL( image->file );
image->rowSize[row] = nRLEBytes;
image->rleTableDirty = TRUE;
if( (int) VSIFWriteL(pabyRLEBuf, 1, nRLEBytes, image->file) != nRLEBytes )
{
CPLFree( pabyRLEBuf );
CPLError(CE_Failure, CPLE_OpenFailed,
"file write error: row (%d)\n", nBlockYOff );
return CE_Failure;
}
CPLFree( pabyRLEBuf );
return CE_None;
}
/************************************************************************/
/* GetColorInterpretation() */
/************************************************************************/
GDALColorInterp SGIRasterBand::GetColorInterpretation()
{
SGIDataset* poGDS = (SGIDataset*)poDS;
if(poGDS->nBands == 1)
return GCI_GrayIndex;
else if(poGDS->nBands == 2)
{
if(nBand == 1)
return GCI_GrayIndex;
else
return GCI_AlphaBand;
}
else if(poGDS->nBands == 3)
{
if(nBand == 1)
return GCI_RedBand;
else if(nBand == 2)
return GCI_GreenBand;
else
return GCI_BlueBand;
}
else if(poGDS->nBands == 4)
{
if(nBand == 1)
return GCI_RedBand;
else if(nBand == 2)
return GCI_GreenBand;
else if(nBand == 3)
return GCI_BlueBand;
else
return GCI_AlphaBand;
}
return GCI_Undefined;
}
/************************************************************************/
/* ==================================================================== */
/* SGIDataset */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* SGIDataset() */
/************************************************************************/
SGIDataset::SGIDataset()
: fpImage(NULL),
bGeoTransformValid(FALSE)
{
adfGeoTransform[0] = 0.0;
adfGeoTransform[1] = 1.0;
adfGeoTransform[2] = 0.0;
adfGeoTransform[3] = 0.0;
adfGeoTransform[4] = 0.0;
adfGeoTransform[5] = 1.0;
}
/************************************************************************/
/* ~SGIDataset() */
/************************************************************************/
SGIDataset::~SGIDataset()
{
FlushCache();
// Do we need to write out rle table?
if( image.rleTableDirty )
{
CPLDebug( "SGI", "Flushing RLE offset table." );
ConvertLong( image.rowStart, image.ysize * image.zsize );
ConvertLong( (GUInt32 *) image.rowSize, image.ysize * image.zsize );
VSIFSeekL( fpImage, 512, SEEK_SET );
VSIFWriteL( image.rowStart, 4, image.ysize * image.zsize, fpImage );
VSIFWriteL( image.rowSize, 4, image.ysize * image.zsize, fpImage );
image.rleTableDirty = FALSE;
}
if(fpImage != NULL)
VSIFCloseL(fpImage);
CPLFree(image.tmp);
CPLFree(image.rowSize);
CPLFree(image.rowStart);
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr SGIDataset::GetGeoTransform(double * padfTransform)
{
if(bGeoTransformValid)
{
memcpy(padfTransform, adfGeoTransform, sizeof(double)*6);
return CE_None;
}
else
return GDALPamDataset::GetGeoTransform(padfTransform);
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
{
/* -------------------------------------------------------------------- */
/* First we check to see if the file has the expected header */
/* bytes. */
/* -------------------------------------------------------------------- */
if(poOpenInfo->nHeaderBytes < 12)
return NULL;
ImageRec tmpImage;
memcpy(&tmpImage, poOpenInfo->pabyHeader, 12);
tmpImage.Swap();
if(tmpImage.imagic != 474)
return NULL;
if (tmpImage.type != 0 && tmpImage.type != 1)
return NULL;
if (tmpImage.bpc != 1 && tmpImage.bpc != 2)
return NULL;
if (tmpImage.dim != 1 && tmpImage.dim != 2 && tmpImage.dim != 3)
return NULL;
if(tmpImage.bpc != 1)
{
CPLError(CE_Failure, CPLE_NotSupported,
"The SGI driver only supports 1 byte channel values.\n");
return NULL;
}
/* -------------------------------------------------------------------- */
/* Create a corresponding GDALDataset. */
/* -------------------------------------------------------------------- */
SGIDataset* poDS;
poDS = new SGIDataset();
poDS->eAccess = poOpenInfo->eAccess;
/* -------------------------------------------------------------------- */
/* Open the file using the large file api. */
/* -------------------------------------------------------------------- */
if( poDS->eAccess == GA_ReadOnly )
poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
else
poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
if(poDS->fpImage == NULL)
{
CPLError(CE_Failure, CPLE_OpenFailed,
"VSIFOpenL(%s) failed unexpectedly in sgidataset.cpp\n%s",
poOpenInfo->pszFilename,
VSIStrerror( errno ) );
delete poDS;
return NULL;
}
/* -------------------------------------------------------------------- */
/* Read pre-image data after ensuring the file is rewound. */
/* -------------------------------------------------------------------- */
VSIFSeekL(poDS->fpImage, 0, SEEK_SET);
if(VSIFReadL((void*)(&(poDS->image)), 1, 12, poDS->fpImage) != 12)
{
CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading header in sgidataset.cpp");
delete poDS;
return NULL;
}
poDS->image.Swap();
poDS->image.file = poDS->fpImage;
poDS->image.fileName = poOpenInfo->pszFilename;
/* -------------------------------------------------------------------- */
/* Capture some information from the file that is of interest. */
/* -------------------------------------------------------------------- */
poDS->nRasterXSize = poDS->image.xsize;
poDS->nRasterYSize = poDS->image.ysize;
if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
{
CPLError(CE_Failure, CPLE_OpenFailed,
"Invalid image dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize);
delete poDS;
return NULL;
}
poDS->nBands = MAX(1,poDS->image.zsize);
if (poDS->nBands > 256)
{
CPLError(CE_Failure, CPLE_OpenFailed,
"Too many bands : %d", poDS->nBands);
delete poDS;
return NULL;
}
int numItems = (int(poDS->image.bpc) == 1) ? 256 : 65536;
poDS->image.tmp = (unsigned char*)VSICalloc(poDS->image.xsize,numItems);
if (poDS->image.tmp == NULL)
{
CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
delete poDS;
return NULL;
}
/* -------------------------------------------------------------------- */
/* Read RLE Pointer tables. */
/* -------------------------------------------------------------------- */
if(int(poDS->image.type) == 1) // RLE compressed
{
int x = poDS->image.ysize * poDS->nBands * sizeof(GUInt32);
poDS->image.rowStart = (GUInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
poDS->image.rowSize = (GInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
if (poDS->image.rowStart == NULL || poDS->image.rowSize == NULL)
{
CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
delete poDS;
return NULL;
}
memset(poDS->image.rowStart, 0, x);
memset(poDS->image.rowSize, 0, x);
poDS->image.rleEnd = 512 + (2 * x);
VSIFSeekL(poDS->fpImage, 512, SEEK_SET);
if((int) VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file) != x)
{
delete poDS;
CPLError(CE_Failure, CPLE_OpenFailed,
"file read error while reading start positions in sgidataset.cpp");
return NULL;
}
if((int) VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x)
{
delete poDS;
CPLError(CE_Failure, CPLE_OpenFailed,
"file read error while reading row lengths in sgidataset.cpp");
return NULL;
}
ConvertLong(poDS->image.rowStart, x/(int)sizeof(GUInt32));
ConvertLong((GUInt32*)poDS->image.rowSize, x/(int)sizeof(GInt32));
}
else // uncompressed.
{
poDS->image.rowStart = NULL;
poDS->image.rowSize = NULL;
}
/* -------------------------------------------------------------------- */
/* Create band information objects. */
/* -------------------------------------------------------------------- */
for(int iBand = 0; iBand < poDS->nBands; iBand++)
poDS->SetBand(iBand+1, new SGIRasterBand(poDS, iBand+1));
/* -------------------------------------------------------------------- */
/* Check for world file. */
/* -------------------------------------------------------------------- */
poDS->bGeoTransformValid =
GDALReadWorldFile(poOpenInfo->pszFilename, ".wld",
poDS->adfGeoTransform);
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
poDS->SetDescription(poOpenInfo->pszFilename);
poDS->TryLoadXML();
/* -------------------------------------------------------------------- */
/* Check for overviews. */
/* -------------------------------------------------------------------- */
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
return poDS;
}
/************************************************************************/
/* Create() */
/************************************************************************/
GDALDataset *SGIDataset::Create( const char * pszFilename,
int nXSize,
int nYSize,
int nBands,
GDALDataType eType,
CPL_UNUSED char **papszOptions )
{
if( eType != GDT_Byte )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create SGI dataset with an illegal\n"
"data type (%s), only Byte supported by the format.\n",
GDALGetDataTypeName(eType) );
return NULL;
}
/* -------------------------------------------------------------------- */
/* Open the file for output. */
/* -------------------------------------------------------------------- */
VSILFILE *fp = VSIFOpenL( pszFilename, "w" );
if( fp == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to create file '%s': %s",
pszFilename, VSIStrerror( errno ) );
return NULL;
}
/* -------------------------------------------------------------------- */
/* Prepare and write 512 byte header. */
/* -------------------------------------------------------------------- */
GByte abyHeader[512];
GInt16 nShortValue;
GInt32 nIntValue;
memset( abyHeader, 0, 512 );
abyHeader[0] = 1;
abyHeader[1] = 218;
abyHeader[2] = 1; // RLE
abyHeader[3] = 1; // 8bit
if( nBands == 1 )
nShortValue = CPL_MSBWORD16(2);
else
nShortValue = CPL_MSBWORD16(3);
memcpy( abyHeader + 4, &nShortValue, 2 );
nShortValue = CPL_MSBWORD16(nXSize);
memcpy( abyHeader + 6, &nShortValue, 2 );
nShortValue = CPL_MSBWORD16(nYSize);
memcpy( abyHeader + 8, &nShortValue, 2 );
nShortValue = CPL_MSBWORD16(nBands);
memcpy( abyHeader + 10, &nShortValue, 2 );
nIntValue = CPL_MSBWORD32(0);
memcpy( abyHeader + 12, &nIntValue, 4 );
nIntValue = CPL_MSBWORD32(255);
memcpy( abyHeader + 16, &nIntValue, 4 );
VSIFWriteL( abyHeader, 1, 512, fp );
/* -------------------------------------------------------------------- */
/* Create our RLE compressed zero-ed dummy line. */
/* -------------------------------------------------------------------- */
GByte *pabyRLELine;
GInt32 nRLEBytes = 0;
int nPixelsRemaining = nXSize;
pabyRLELine = (GByte *) CPLMalloc((nXSize/127) * 2 + 4);
while( nPixelsRemaining > 0 )
{
pabyRLELine[nRLEBytes] = (GByte) MIN(127,nPixelsRemaining);
pabyRLELine[nRLEBytes+1] = 0;
nPixelsRemaining -= pabyRLELine[nRLEBytes];
nRLEBytes += 2;
}
/* -------------------------------------------------------------------- */
/* Prepare and write RLE offset/size tables with everything */
/* zeroed indicating dummy lines. */
/* -------------------------------------------------------------------- */
int i;
int nTableLen = nYSize * nBands;
GInt32 nDummyRLEOffset = 512 + 4 * nTableLen * 2;
CPL_MSBPTR32( &nRLEBytes );
CPL_MSBPTR32( &nDummyRLEOffset );
for( i = 0; i < nTableLen; i++ )
VSIFWriteL( &nDummyRLEOffset, 1, 4, fp );
for( i = 0; i < nTableLen; i++ )
VSIFWriteL( &nRLEBytes, 1, 4, fp );
/* -------------------------------------------------------------------- */
/* write the dummy RLE blank line. */
/* -------------------------------------------------------------------- */
CPL_MSBPTR32( &nRLEBytes );
if( (GInt32) VSIFWriteL( pabyRLELine, 1, nRLEBytes, fp ) != nRLEBytes )
{
CPLError( CE_Failure, CPLE_FileIO,
"Failure writing SGI file '%s'.\n%s",
pszFilename,
VSIStrerror( errno ) );
return NULL;
}
VSIFCloseL( fp );
CPLFree( pabyRLELine );
return (GDALDataset*) GDALOpen( pszFilename, GA_Update );
}
/************************************************************************/
/* GDALRegister_SGI() */
/************************************************************************/
void GDALRegister_SGI()
{
GDALDriver* poDriver;
if(GDALGetDriverByName("SGI") == NULL)
{
poDriver = new GDALDriver();
poDriver->SetDescription("SGI");
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
"SGI Image File Format 1.0");
poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rgb");
poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/rgb");
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
"frmt_various.html#SGI" );
poDriver->pfnOpen = SGIDataset::Open;
poDriver->pfnCreate = SGIDataset::Create;
poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
GetGDALDriverManager()->RegisterDriver(poDriver);
}
}