Esempio n. 1
0
void vtBitmapBase::ScalePixel8(int x, int y, float fScale)
{
	uint texel = (int) (GetPixel8(x, y) * fScale);
	if (texel > 255)
		texel = 255;
	SetPixel8(x, y, (uchar) texel);
}
Esempio n. 2
0
bool vtImageGeo::ReadTIF(const char *filename, bool progress_callback(int))
{
	// Use GDAL to read a TIF file (or any other format that GDAL is
	//  configured to read) into this OSG image.
	bool bRet = true;
	vtString message;

	setFileName(filename);

	g_GDALWrapper.RequestGDALFormats();

	GDALDataset *pDataset = NULL;
	GDALRasterBand *pBand;
	GDALRasterBand *pRed = NULL;
	GDALRasterBand *pGreen = NULL;
	GDALRasterBand *pBlue = NULL;
	GDALRasterBand *pAlpha = NULL;
	GDALColorTable *pTable;
	uchar *pScanline = NULL;
	uchar *pRedline = NULL;
	uchar *pGreenline = NULL;
	uchar *pBlueline = NULL;
	uchar *pAlphaline = NULL;

	CPLErr Err;
	bool bColorPalette = false;
	int iXSize, iYSize;
	int nxBlocks, nyBlocks;
	int xBlockSize, yBlockSize;

	try
	{
		pDataset = (GDALDataset *) GDALOpen(filename, GA_ReadOnly);
		if(pDataset == NULL )
			throw "Couldn't open that file.";

		// Get size
		iXSize = pDataset->GetRasterXSize();
		iYSize = pDataset->GetRasterYSize();

		// Try getting CRS
		vtProjection temp;
		bool bHaveProj = false;
		const char *pProjectionString = pDataset->GetProjectionRef();
		if (pProjectionString)
		{
			OGRErr err = temp.importFromWkt((char**)&pProjectionString);
			if (err == OGRERR_NONE)
			{
				m_proj = temp;
				bHaveProj = true;
			}
		}
		if (!bHaveProj)
		{
			// check for existence of .prj file
			bool bSuccess = temp.ReadProjFile(filename);
			if (bSuccess)
			{
				m_proj = temp;
				bHaveProj = true;
			}
		}

		// Try getting extents
		double affineTransform[6];
		if (pDataset->GetGeoTransform(affineTransform) == CE_None)
		{
			m_extents.left = affineTransform[0];
			m_extents.right = m_extents.left + affineTransform[1] * iXSize;
			m_extents.top = affineTransform[3];
			m_extents.bottom = m_extents.top + affineTransform[5] * iYSize;
		}

		// Raster count should be 3 for colour images (assume RGB)
		int iRasterCount = pDataset->GetRasterCount();

		if (iRasterCount != 1 && iRasterCount != 3 && iRasterCount != 4)
		{
			message.Format("Image has %d bands (not 1, 3, or 4).", iRasterCount);
			throw (const char *)message;
		}

		if (iRasterCount == 1)
		{
			pBand = pDataset->GetRasterBand(1);

			// Check the band's data type
			GDALDataType dtype = pBand->GetRasterDataType();
			if (dtype != GDT_Byte)
			{
				message.Format("Band is of type %s, but we support type Byte.", GDALGetDataTypeName(dtype));
				throw (const char *)message;
			}
			GDALColorInterp ci = pBand->GetColorInterpretation();

			if (ci == GCI_PaletteIndex)
			{
				if (NULL == (pTable = pBand->GetColorTable()))
					throw "Couldn't get color table.";
				bColorPalette = true;
			}
			else if (ci == GCI_GrayIndex)
			{
				// we will assume 0-255 is black to white
			}
			else
				throw "Unsupported color interpretation.";

			pBand->GetBlockSize(&xBlockSize, &yBlockSize);
			nxBlocks = (iXSize + xBlockSize - 1) / xBlockSize;
			nyBlocks = (iYSize + yBlockSize - 1) / yBlockSize;
			if (NULL == (pScanline = new uchar[xBlockSize * yBlockSize]))
				throw "Couldnt allocate scan line.";
		}

		if (iRasterCount == 3)
		{
			for (int i = 1; i <= 3; i++)
			{
				pBand = pDataset->GetRasterBand(i);

				// Check the band's data type
				GDALDataType dtype = pBand->GetRasterDataType();
				if (dtype != GDT_Byte)
				{
					message.Format("Band is of type %s, but we support type Byte.", GDALGetDataTypeName(dtype));
					throw (const char *)message;
				}
				switch (pBand->GetColorInterpretation())
				{
				case GCI_RedBand:
					pRed = pBand;
					break;
				case GCI_GreenBand:
					pGreen = pBand;
					break;
				case GCI_BlueBand:
					pBlue = pBand;
					break;
				}
			}
			if ((NULL == pRed) || (NULL == pGreen) || (NULL == pBlue))
				throw "Couldn't find bands for Red, Green, Blue.";

			pRed->GetBlockSize(&xBlockSize, &yBlockSize);
			nxBlocks = (iXSize + xBlockSize - 1) / xBlockSize;
			nyBlocks = (iYSize + yBlockSize - 1) / yBlockSize;

			pRedline = new uchar[xBlockSize * yBlockSize];
			pGreenline = new uchar[xBlockSize * yBlockSize];
			pBlueline = new uchar[xBlockSize * yBlockSize];
		}

		if (iRasterCount == 4)
		{
#if VTDEBUG
			VTLOG1("Band interpretations:");
#endif
			for (int i = 1; i <= 4; i++)
			{
				pBand = pDataset->GetRasterBand(i);

				// Check the band's data type
				GDALDataType dtype = pBand->GetRasterDataType();
				if (dtype != GDT_Byte)
				{
					message.Format("Band is of type %s, but we support type Byte.", GDALGetDataTypeName(dtype));
					throw (const char *)message;
				}
				GDALColorInterp ci = pBand->GetColorInterpretation();
#if VTDEBUG
				VTLOG(" %d", ci);
#endif
				switch (ci)
				{
				case GCI_RedBand:
					pRed = pBand;
					break;
				case GCI_GreenBand:
					pGreen = pBand;
					break;
				case GCI_BlueBand:
					pBlue = pBand;
					break;
				case GCI_AlphaBand:
					pAlpha = pBand;
					break;
				case GCI_Undefined:
					// If we have four bands: R,G,B,undefined, then assume that
					//  the undefined one is actually alpha
					if (pRed && pGreen && pBlue && !pAlpha)
						pAlpha = pBand;
					break;
				}
			}
#if VTDEBUG
			VTLOG1("\n");
#endif
			if ((NULL == pRed) || (NULL == pGreen) || (NULL == pBlue) || (NULL == pAlpha))
				throw "Couldn't find bands for Red, Green, Blue, Alpha.";

			pRed->GetBlockSize(&xBlockSize, &yBlockSize);
			nxBlocks = (iXSize + xBlockSize - 1) / xBlockSize;
			nyBlocks = (iYSize + yBlockSize - 1) / yBlockSize;

			pRedline = new uchar[xBlockSize * yBlockSize];
			pGreenline = new uchar[xBlockSize * yBlockSize];
			pBlueline = new uchar[xBlockSize * yBlockSize];
			pAlphaline = new uchar[xBlockSize * yBlockSize];
		}

		// Allocate the image buffer
		if (iRasterCount == 4)
		{
			Create(iXSize, iYSize, 32);
		}
		else if (iRasterCount == 3 || bColorPalette)
		{
			Create(iXSize, iYSize, 24);
		}
		else if (iRasterCount == 1)
			Create(iXSize, iYSize, 8);

		// Read the data
#if LOG_IMAGE_LOAD
		VTLOG("Reading the image data (%d x %d pixels)\n", iXSize, iYSize);
#endif

		int x, y;
		int ixBlock, iyBlock;
		int nxValid, nyValid;
		int iY, iX;
		RGBi rgb;
		RGBAi rgba;
		if (iRasterCount == 1)
		{
			GDALColorEntry Ent;
			for (iyBlock = 0; iyBlock < nyBlocks; iyBlock++)
			{
				if (progress_callback != NULL)
					progress_callback(iyBlock * 100 / nyBlocks);

				y = iyBlock * yBlockSize;
				for (ixBlock = 0; ixBlock < nxBlocks; ixBlock++)
				{
					x = ixBlock * xBlockSize;
					Err = pBand->ReadBlock(ixBlock, iyBlock, pScanline);
					if (Err != CE_None)
						throw "Problem reading the image data.";

					// Compute the portion of the block that is valid
					// for partial edge blocks.
					if ((ixBlock+1) * xBlockSize > iXSize)
						nxValid = iXSize - ixBlock * xBlockSize;
					else
						nxValid = xBlockSize;

					if( (iyBlock+1) * yBlockSize > iYSize)
						nyValid = iYSize - iyBlock * yBlockSize;
					else
						nyValid = yBlockSize;

					for( iY = 0; iY < nyValid; iY++ )
					{
						for( iX = 0; iX < nxValid; iX++ )
						{
							if (bColorPalette)
							{
								pTable->GetColorEntryAsRGB(pScanline[iY * xBlockSize + iX], &Ent);
								rgb.r = (uchar) Ent.c1;
								rgb.g = (uchar) Ent.c2;
								rgb.b = (uchar) Ent.c3;
								SetPixel24(x + iX, y + iY, rgb);
							}
							else
								SetPixel8(x + iX, y + iY, pScanline[iY * xBlockSize + iX]);
						}
					}
				}
			}
		}
		if (iRasterCount >= 3)
		{
			for (iyBlock = 0; iyBlock < nyBlocks; iyBlock++)
			{
				if (progress_callback != NULL)
					progress_callback(iyBlock * 100 / nyBlocks);

				y = iyBlock * yBlockSize;
				for (ixBlock = 0; ixBlock < nxBlocks; ixBlock++)
				{
					x = ixBlock * xBlockSize;
					Err = pRed->ReadBlock(ixBlock, iyBlock, pRedline);
					if (Err != CE_None)
						throw "Cannot read data.";
					Err = pGreen->ReadBlock(ixBlock, iyBlock, pGreenline);
					if (Err != CE_None)
						throw "Cannot read data.";
					Err = pBlue->ReadBlock(ixBlock, iyBlock, pBlueline);
					if (Err != CE_None)
						throw "Cannot read data.";
					if (iRasterCount == 4)
					{
						Err = pAlpha->ReadBlock(ixBlock, iyBlock, pAlphaline);
						if (Err != CE_None)
							throw "Cannot read data.";
					}

					// Compute the portion of the block that is valid
					// for partial edge blocks.
					if ((ixBlock+1) * xBlockSize > iXSize)
						nxValid = iXSize - ixBlock * xBlockSize;
					else
						nxValid = xBlockSize;

					if( (iyBlock+1) * yBlockSize > iYSize)
						nyValid = iYSize - iyBlock * yBlockSize;
					else
						nyValid = yBlockSize;

					for (int iY = 0; iY < nyValid; iY++)
					{
						for (int iX = 0; iX < nxValid; iX++)
						{
							if (iRasterCount == 3)
							{
								rgb.r = pRedline[iY * xBlockSize + iX];
								rgb.g = pGreenline[iY * xBlockSize + iX];
								rgb.b = pBlueline[iY * xBlockSize + iX];
								SetPixel24(x + iX, y + iY, rgb);
							}
							else if (iRasterCount == 4)
							{
								rgba.r = pRedline[iY * xBlockSize + iX];
								rgba.g = pGreenline[iY * xBlockSize + iX];
								rgba.b = pBlueline[iY * xBlockSize + iX];
								rgba.a = pAlphaline[iY * xBlockSize + iX];
								SetPixel32(x + iX, y + iY, rgba);
							}
						}
					}
				}
			}
		}
	}
	catch (const char *msg)
	{
		VTLOG1("Problem: ");
		VTLOG1(msg);
		VTLOG1("\n");
		bRet = false;
	}

	if (NULL != pDataset)
		GDALClose(pDataset);
	if (NULL != pScanline)
		delete pScanline;
	if (NULL != pRedline)
		delete pRedline;
	if (NULL != pGreenline)
		delete pGreenline;
	if (NULL != pBlueline)
		delete pBlueline;
	if (NULL != pAlphaline)
		delete pAlphaline;

	return bRet;
}