[Gdal-dev] Writing bit interleaved
datawith GDALRasterBand::RasterIO
Alain Rist
ar at navpoch.com
Wed Jul 7 13:11:23 EDT 2004
Hi Martin,
This is what I wrote for GDALView.
Hope it helps.
Alain
----- Original Message -----
From: "Chapman, Martin" <MChapman at sanz.com>
To: "Frank Warmerdam" <warmerdam at pobox.com>
Cc: "gdal-dev" <gdal-dev at remotesensing.org>
Sent: Wednesday, July 07, 2004 6:35 PM
Subject: RE: [Gdal-dev] Writing bit interleaved datawith
GDALRasterBand::RasterIO
Frank,
I'm not sure if I mean byte or pixel interleave. I want to save data
the I have in a windows DIB. When I create the DIB from a gdal dataset
I interleave the bits into the following structure something like
this...
unsigned char* pCombinedBytes = (unsigned char*)
CPLMalloc(sizeof(unsigned char) * nWidth * nHeight * nSize);
//Where nSize is the number of bands and nWidth and nHeight is the aoi w
and h...
//then I retrieve the bytes for each band something like this...
void** pBandBuffer = (void**) new unsigned char*[nSize];
//for each band
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;
//end if
// then I interleave the bytes into one array...
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);
}
}
// then I realign the bytes for a windows DIB...
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);
}
So I think I am pixel interleaving then? Anyway, I think the example
you sent me will work if I undo the windows DIB realignment, (which
would be really cool). I'll let you know if it works.
Thanks for the quick response.
Martin
-----Original Message-----
From: Frank Warmerdam [mailto:warmerdam at pobox.com]
Sent: Wednesday, July 07, 2004 10:02 AM
To: Chapman, Martin
Cc: gdal-dev
Subject: Re: [Gdal-dev] Writing bit interleaved data with
GDALRasterBand::RasterIO
Chapman, Martin wrote:
> All,
>
> If I have raster data stored as bit interleaved
> (r,g,b,r,g,b,r,g,b...),
> can I use the GDALRasterBand::RasterIO function to write this data to
> disc? I read that the nPixelSpace and nLineSpace parameters allow
> reading into or writing from unusually organized buffers. If this is
> possible, could someone please provide me a brief example of how to
use
> these parameters with this type of data structure?
Martin,
Do you literally mean bit interleaved? Or pixel interleaved?
I'll assume you mean pixel interleaved. To write from a pixel
interleaved
1 line buffer of 8bit data you might use:
poBandRed->RasterIO( GF_Write, 0, line, xsize, 1,
pabyRGB + 0, xsize, 1, GDT_Byte,
3, xsize * 3 );
poBandGreen->RasterIO( GF_Write, 0, line, xsize, 1,
pabyRGB + 1, xsize, 1, GDT_Byte,
3, xsize * 3 );
poBandBlue->RasterIO( GF_Write, 0, line, xsize, 1,
pabyRGB + 2, xsize, 1, GDT_Byte,
3, xsize * 3 );
Note that the buffer pointer you pass in needs to point to the beginning
of the data to be written (hence the +1 and +2 offsets on pabyRGB for
green and blue). The nPixelSpace is the number of bytes from the
beginning of one pixel to the beginning of the next. 3 in this case
since there are 3 bytes of data for for each pixel written. The
linespacing is the offset from the beginning of one line to the next, so
xsize * 3 in this case.
I hope this helps. If your data is really "bit" interleaved you will
need to repack stuff before writing.
Best regards,
--
---------------------------------------+--------------------------------
---------------------------------------+------
I set the clouds in motion - turn up | Frank Warmerdam,
warmerdam at pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush | Geospatial Programmer for Rent
_______________________________________________
Gdal-dev mailing list
Gdal-dev at xserve.flids.com
http://xserve.flids.com/mailman/listinfo/gdal-dev
-------------- next part --------------
/******************************************************************************
* Purpose: Create a Windows bitmap from a GDALDataSet.
*
* Author: Alain Rist, ar at navpoch.com
*
******************************************************************************
* Copyright (c) 2004, Alain Rist
*
* 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.
******************************************************************************
*/
#pragma once
#include <windows.h>
#include <gdal_priv.h>
/*
GDALCreateDib returns a HBITMAP from a RGB, grayscale, or 8bits paletted GDALDataset.
Returns NULL if fails.
If the failure comes from Windows(r) ( file too big for this system ) GetLastError() will
return ERROR_NO_SYSTEM_RESOURCES .
Otherwise the format is not implemented.
*/
HBITMAP GDALCreateDib( GDALDataset * poDataset)
{
struct DIBINFO : public BITMAPINFO
{
RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
DIBINFO(BITMAPINFO bm) : BITMAPINFO(bm) {}
operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
RGBQUAD* ColorTable( int i=0 ) { return bmiColors + i ; }
};
BITMAPINFO bm = { sizeof(BITMAPINFOHEADER),
poDataset->GetRasterXSize(), - poDataset->GetRasterYSize(), 1, 24, BI_RGB };
DIBINFO bmi(bm);
int nBands = poDataset->GetRasterCount();
if ( nBands == 1 )
{
bmi.bmiHeader.biBitCount = 8 ;
switch ( poDataset->GetRasterBand(1)->GetColorInterpretation())
{
case GCI_PaletteIndex :
{
GDALColorTable * pgdColorTable = poDataset->GetRasterBand(1)->GetColorTable();
bmi.bmiHeader.biClrUsed = pgdColorTable->GetColorEntryCount();
if ( ( bmi.bmiHeader.biClrUsed > 256 ) ||
( pgdColorTable->GetPaletteInterpretation() != GPI_RGB ))
return NULL; // unsupported image format
// Fill the color table
for ( UINT i=0 ; i < bmi.bmiHeader.biClrUsed ; i++ )
{
bmi.ColorTable(i)->rgbBlue =(BYTE) pgdColorTable->GetColorEntry(i)->c3;
bmi.ColorTable(i)->rgbGreen =(BYTE) pgdColorTable->GetColorEntry(i)->c2;
bmi.ColorTable(i)->rgbRed =(BYTE) pgdColorTable->GetColorEntry(i)->c1;
bmi.ColorTable(i)->rgbReserved = 0;
}
break;
}
case GCI_GrayIndex :
bmi.bmiHeader.biClrUsed = 256 ;
// Fill the color table
for ( UINT i=0 ; i < bmi.bmiHeader.biClrUsed ; i++ )
{
RGBQUAD q = {i,i,i,0} ;
*bmi.ColorTable(i) = q ;
}
break;
default :
return NULL ;
}
}
// Create the DIB
HDC dc = CreateCompatibleDC( NULL );
LPVOID pBits;
HBITMAP hbm = CreateDIBSection( dc, bmi, DIB_RGB_COLORS, &pBits, NULL, NULL );
DeleteDC(dc);
if ( ! hbm )
{
SetLastError( ERROR_NO_SYSTEM_RESOURCES );
LocalFree(pBits);
return hbm;
}
// Fill the Bits
CPLErr gdErr = CE_Failure;
int nScanSize = ((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount + 31) & (~31) ) / 8;
int nBandsRead = 1 ;
if ( bmi.bmiHeader.biBitCount == 8 ) // Paletted or Gray
gdErr = poDataset->GetRasterBand(1)->RasterIO(
GF_Read , 0 ,0 , poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
pBits,bmi.bmiHeader.biWidth,-bmi.bmiHeader.biHeight,GDT_Byte,
1, nScanSize );
else
for ( int iBand = 1 ,nBandsRead = 0 ; iBand <= nBands ; iBand ++ )
{
int iColorOffset;
switch( poDataset->GetRasterBand(iBand)->GetColorInterpretation() )
{ // BGR
case GCI_RedBand : iColorOffset = 2;
break;
case GCI_GreenBand : iColorOffset = 1;
break;
case GCI_BlueBand : iColorOffset = 0;
break;
default : continue ;
}
gdErr = poDataset->GetRasterBand(iBand)->RasterIO(
GF_Read , 0 ,0 , poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
((LPBYTE)pBits) + iColorOffset ,bmi.bmiHeader.biWidth,-bmi.bmiHeader.biHeight,
GDT_Byte, 3, nScanSize );
nBandsRead ++;
}
if (( gdErr != CE_None ) || !nBandsRead )
{
::DeleteObject(hbm);
hbm=NULL;
}
return hbm ;
};
More information about the Gdal-dev
mailing list