[Gdal-dev] how to get pixels' band vector efficiently

Chapman, Martin MChapman at sanz.com
Tue Sep 14 17:41:09 EDT 2004


Andy,

This function let's me read in an area of interest with blistering
results...faster than Erdas can do it.  I only ever read in enough bits
to fill the client rect of the viewing window.  I re-read everytime you
move the window.  I can open and display a 8 gig imgage across the
network in 2 - 3 seconds.  Once it's open, it's instantaneous when
scrolling.  The key is using pointer arithmetic with the ansi memcpy()
function.  I've heard you can make it even faster using ReadBlock(), but
that method doesn't suit the aoi function for me as well....plus this is
already greased lightning.  This code is cut and pasted so I don't know
if it will work out of the gate, but, shouldn't be far off if it
doesn't. (I had to remove a few proprietary things).  Also, the
dibsection class is a helper class for windows rgbs.  Let me know if you
need it, I will send it to you.

CDIBSection* CImagePortDoc::GetAreaOfInterest(CRect rect, int nResLevel)
{

		int nBandCount = m_vBandList.size();
		int nWidth = rect.Width();
		int nHeight = rect.Height();
		int nXOffset = rect.left;
		int nYOffset = rect.top;
		void * ptr_dest = NULL;
		void * ptr_src = NULL;
		m_nResLevel = nResLevel;

		int nSize = 3; // this is always 3 bands because windows
dibs are rgb.
		void** pBandBuffer = (void**) new unsigned char*[nSize];

		GDALColorTable* pCT =
m_pDataset->GetRasterBand(1)->GetColorTable();
		GDALRasterBand* pBand = NULL;
		void* pBandBytes = NULL;

		for (int n = 0; n < nSize; n++)
		{
			if (nBandCount > 1)
				pBand =
m_pDataset->GetRasterBand(m_vBandList[n] + 1);
			else
				pBand = m_pDataset->GetRasterBand(1);

			int nRasterX = pBand->GetXSize();
			int nRasterY = pBand->GetYSize();

			if (nWidth > nRasterX)
			{
				nXOffset = 0;
				nWidth = nRasterX;
			}

			if (nHeight > nRasterY) 
			{
				nYOffset = 0;
				nHeight = nRasterY;
			}

			pBandBytes = (unsigned char*)
CPLMalloc(sizeof(unsigned char) * nWidth * nHeight);
			pBand->RasterIO(GF_Read, nXOffset, nYOffset,
nWidth, nHeight, pBandBytes, nWidth , nHeight, GDT_Byte, 0, 0);
			pBandBuffer[n] = pBandBytes;
		}

		unsigned char* pCombinedBytes = (unsigned char*)
CPLMalloc(sizeof(unsigned char) * nWidth * nHeight * nSize);

		for (long i = 0, long j = 0; i < (nWidth * nHeight *
nSize); i += nSize, j++)
		{
			int k = i;

			for (int m = nSize - 1; m >= 0; m--, k++)
			{
				unsigned char* pBytes = (unsigned char*)
pBandBuffer[m];
				ptr_dest = pCombinedBytes + k;
				unsigned char b = pBytes[j];

				if (pCT != NULL)
				{
					GDALColorEntry ce;
					unsigned int c = (unsigned int)
b;
					c = pCT->GetColorEntryAsRGB(c,
&ce);
					if (m == 0) c = ce.c1;
					if (m == 1) c = ce.c2;
					if (m == 2) c = ce.c3;
					b = (unsigned char) c;
				}

				ptr_src = &b;
				memcpy(ptr_dest, ptr_src, 1);
			}
		}

		if ((nWidth > 0) && (nHeight > 0))
		{
			if (m_pDIBSection) delete m_pDIBSection;
			m_pDIBSection = new CDIBSection;

			if (m_pDIBSection)
			{
				m_pDIBSection->Create(nWidth ,nHeight,
24);
				unsigned int dibwidth =
m_pDIBSection->GetTotalWidth();

				GByte* dest = (GByte*)
m_pDIBSection->GetBits();
				GByte* src = (GByte*) pCombinedBytes;

				for (int row = 0; row < nHeight; row++)
				{
					ptr_dest = dest + row * dibwidth
* nSize;
					ptr_src = src + row * nWidth *
nSize;
					memcpy(ptr_dest, ptr_src, nWidth
* nSize);
				}
			}
		}

		if (pBandBuffer)
		{
			for (int d = 0; d < nSize; d++)
				CPLFree(pBandBuffer[d]);

			delete [] pBandBuffer;
		}

		if (pCombinedBytes)
			CPLFree(pCombinedBytes);

		CDIBSection* pDIBSection = m_pDIBSection;
		return pDIBSection;
}




Martin Chapman

-----Original Message-----
From: Andrew Finley [mailto:afinley at gis.umn.edu] 
Sent: Tuesday, September 14, 2004 3:20 PM
To: gdal-dev at remotesensing.org
Subject: [Gdal-dev] how to get pixels' band vector efficiently


Hi All,
I have written an image classification algorithm which uses gdal to fill
a vector of band values for each pixel.  I'm looking for a better/faster
way of accessing these values. Two general ways I might think to speed
this up are: 

1) move one tile at a time into memory then apply the loop below.
2) find a way to load my target vector more efficiently than one
pixel/layer at a time.

So I guess I'm looking for some ideas or example code.  Could the
tileindex application offer any help? Does it load logical image blocks
(i.e., from a single page)?

Thanks a lot for suggestions.
-Andy

Current approach:
//every pixel loop
for (int row = 0; row < featureDataset->GetRasterYSize(); row++){
	for (int col = 0; col < featureDataset->GetRasterXSize();
col++){

	//fill targetBandVec
	for (layer = 1; layer <= featureDataset->GetRasterCount();
layer++){
		featureBand = featureDataset->GetRasterBand( layer );
		featureBand->RasterIO(GF_Read, col, row, 1, 1,
featurePixel, 1, 1, GDT_Float32, 0, 0 );
		targetBandVec[layer-1]=featurePixel[0];
	}

	Then classify the target vector...

	}
}


-- 
Andrew Finley, Research Fellow
Department of Forest Resources
College of Natural Resources           
University of Minnesota
305 Green Hall
1530 Cleveland Avenue N.
St. Paul, MN 55108

Ph 612-624-1714 office
www.cnr.umn.edu/FR/people/facstaff/finley/index.html
_______________________________________________
Gdal-dev mailing list
Gdal-dev at xserve.flids.com
http://xserve.flids.com/mailman/listinfo/gdal-dev



More information about the Gdal-dev mailing list