virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pData ) { return poUnderlyingBand->ReadBlock(nBlockXOff, nBlockYOff, pData); }
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; }
bool DEM::load(const std::string& filename) { GDALAllRegister(); GDALDataset* poDS; poDS = (GDALDataset*)GDALOpenEx(filename.c_str(), GDAL_OF_RASTER, NULL, NULL, NULL); if (poDS == NULL) return false; double adfGeoTransform[6]; if (poDS->GetGeoTransform(adfGeoTransform) == CE_None) { origin.x = adfGeoTransform[0]; origin.y = adfGeoTransform[3]; pixelSize.x = adfGeoTransform[1]; pixelSize.y = abs(adfGeoTransform[5]); } width = poDS->GetRasterXSize() * pixelSize.x; height = poDS->GetRasterYSize() * pixelSize.y; data.resize(width * height); min_val = std::numeric_limits<float>::max(); max_val = -std::numeric_limits<float>::max(); // bandが存在しない場合は、エラー if (poDS->GetRasterCount() == 0) return false; // 最初のbandのみを読み込む。複数bandは未対応 GDALRasterBand* poBand = poDS->GetRasterBand(1); int nBlockXSize, nBlockYSize; poBand->GetBlockSize(&nBlockXSize, &nBlockYSize); //printf("Block=%dx%d Type=%s, ColorInterp=%s\n", nBlockXSize, nBlockYSize, GDALGetDataTypeName(poBand->GetRasterDataType()), GDALGetColorInterpretationName(poBand->GetColorInterpretation())); // 最低、最高の値を取得 int bGotMin, bGotMax; double adfMinMax[2]; adfMinMax[0] = poBand->GetMinimum(&bGotMin); adfMinMax[1] = poBand->GetMaximum(&bGotMax); if (!(bGotMin && bGotMax)) GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax); //printf("Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1]); min_val = adfMinMax[0]; max_val = adfMinMax[1]; //int nXSize = poBand->GetXSize(); //int nYSize = poBand->GetYSize(); int nXBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize; int nYBlocks = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize; float *pData = (float *)CPLMalloc(sizeof(float*) * nBlockXSize * nBlockYSize); for (int iYBlock = 0; iYBlock < nYBlocks; iYBlock++) { for (int iXBlock = 0; iXBlock < nXBlocks; iXBlock++) { int nXValid, nYValid; poBand->ReadBlock(iXBlock, iYBlock, pData); // Compute the portion of the block that is valid // for partial edge blocks. if ((iXBlock + 1) * nBlockXSize > poBand->GetXSize()) nXValid = poBand->GetXSize() - iXBlock * nBlockXSize; else nXValid = nBlockXSize; if ((iYBlock + 1) * nBlockYSize > poBand->GetYSize()) nYValid = poBand->GetYSize() - iYBlock * nBlockYSize; else nYValid = nBlockYSize; for (int iY = 0; iY < nYValid; iY++) { for (int iX = 0; iX < nXValid; iX++) { float val; if (pData[iY * nBlockXSize + iX] > max_val) { val = max_val; } else if (pData[iY * nBlockXSize + iX] < min_val) { val = min_val; } else { val = pData[iY * nBlockXSize + iX]; } for (int y = 0; y < pixelSize.y; ++y) { for (int x = 0; x < pixelSize.x; ++x) { data[((iYBlock * nBlockYSize + iY) * pixelSize.y + y) * width + (iXBlock * nBlockXSize + iX) * pixelSize.x + x] = val; } } } } } } GDALClose(poDS); return true; }