How to directly pass bitmap bits into PushPixelData call...
- From: Hans <kuykens@xxxxxx>
- Date: Fri, 17 Aug 2007 12:06:58 -0000
I am struggling some days with the following issue. The goal is to
paint to a memory bitmap and save this bitmap into a JPG file using
the Imaging library.
Included below are two code clips that should do it...
The problem occurs in the PushPixelData call: it always returns with
an invalid argument error.
Anybody have experience with this or give me a pointer how to solve
this?
regards:
Hans Kuykens
....start code clip <<
CBitmap Bitmap;
BYTE * pBits = new BYTE[100*100*3];
Bitmap.CreateBitmap( 100 , 100 , 1 , 24 , pBits );
CDC memDC;
memDC.CreateCompatibleDC( pDC );
CBitmap * pOldBitmap = memDC.SelectObject( &Bitmap );
CPen Pen(PS_SOLID , 2 , RGB(255,0,0) );
CPen * pOldPen = memDC.SelectObject( &Pen );
CBrush Brush;
Brush.CreateSolidBrush( RGB(255,255,255) );
memDC.FillRect( CRect(0,0,100,100) , &Brush );
memDC.MoveTo(0,0);
memDC.LineTo( 100,100);
memDC.SelectObject( pOldPen );
memDC.SelectObject( pOldBitmap );
pWnd->ReleaseDC( pDC );
BITMAP bm;
Bitmap.GetObject( sizeof(BITMAP) , &bm );
SaveImageToFile( bm , pBits );
...
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SaveImageToFile
( BITMAP & rBM
, LPVOID lpBits
)
{
IImagingFactory *pImgFactory = 0;
if( !SUCCEEDED( CoCreateInstance (CLSID_ImagingFactory, NULL,
CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&pImgFactory) ) )
return;
UINT count;
CLSID clsid;
UINT num = 1;
//UINT totalBuffer = 16;
const wchar_t* formatString = _T("image/jpeg");
ImageCodecInfo* imageCodecInfo = NULL;
HRESULT hRes = pImgFactory->GetInstalledEncoders(&count,
&imageCodecInfo);
if( !SUCCEEDED( hRes ) )
{
return;
}
for(UINT i=0; i < count; i++)
{
if(wcscmp(imageCodecInfo [ i ].MimeType, formatString) == 0)
{
clsid = imageCodecInfo [ i ].Clsid;
CoTaskMemFree( imageCodecInfo );
//free(imageCodecInfo);
break;
}
else
{
continue;
}
}
IImageEncoder* pEncoder = NULL;
if( !SUCCEEDED( pImgFactory->CreateImageEncoderToFile(&clsid,
TEXT("demo1.jpg"), &pEncoder) ) )
return;
IImageSink* pSink = 0;
if( !SUCCEEDED( pEncoder->GetEncodeSink(&pSink) ) )
return;
// retrieve information about the bitmap...
BITMAP bm( rBM );
//rBitmap.GetBitmap( &bm );
UINT numColors=0;
PixelFormatID pixelFormat;
switch (bm.bmBitsPixel)
{
case 1:
{
pixelFormat = PixelFormat1bppIndexed;
numColors = 1;
break;
}
case 4:
{
pixelFormat = PixelFormat4bppIndexed;
numColors = 16;
break;
}
case 8:
{
pixelFormat = PixelFormat8bppIndexed;
numColors = 256;
break;
}
case 16:
{
pixelFormat = PixelFormat16bppRGB555;
numColors = 0;
break;
}
case 24:
{
pixelFormat = PixelFormat24bppRGB;
numColors = 0;
break;
}
default:
{
pixelFormat = PixelFormat32bppARGB;
break;
}
}
// imageInfo should describe the data produced by the source.
ImageInfo imageInfo;
ZeroMemory( &imageInfo , sizeof( ImageInfo ) );
imageInfo.Width = bm.bmWidth;
imageInfo.Height = bm.bmHeight;
imageInfo.RawDataFormat = IMGFMT_MEMORYBMP; // ImageFormatJPEG;
ImageFormatMemoryBMP;
imageInfo.Flags |= SinkFlagsTopDown | SinkFlagsFullWidth;
imageInfo.PixelFormat = pixelFormat;
//imageInfo.TileWidth = bm.bmWidth;
//imageInfo.TileHeight = bm.bmHeight;
//imageInfo.Xdpi = 72.0;
//imageInfo.Ydpi = 72.0;
if (pixelFormat == PixelFormat32bppARGB)
{
imageInfo.Flags |= SinkFlagsHasAlpha;
}
RECT SubRect;
if( !SUCCEEDED( pSink->BeginSink(&imageInfo, &SubRect) ) )
return;
//ASSERT( imageInfo->RawDataFormat==IMGFMT_MEMORYBMP ); // link
error...
// HK says: this seems to create a generic color pallette instead of
// getting the true pallette of the bitmap
ColorPalette* palette = NULL;
if (numColors > 0) {
palette = (ColorPalette*)malloc(sizeof(ColorPalette) +
(numColors - 1) * sizeof(ARGB));
palette->Flags = 0;
palette->Count = numColors;
for (UINT i=0; i<numColors; i++) {
int rgb = i*64;
int red = rgb & 0x00FF;
int green = (rgb >> 8) & 0x00FF;
int blue = (rgb >> 16) & 0x00FF;
palette->Entries [ i ] = MAKEARGB(0, red, green, blue);
}
} else {
palette = (ColorPalette*)malloc(sizeof(ColorPalette));
palette->Count = 0;
if (pixelFormat == PixelFormat32bppARGB)
{
palette->Flags = PALFLAG_HASALPHA;
}
}
if( !SUCCEEDED( pSink->SetPalette(palette) ))
return;
BitmapData bmData;
ZeroMemory( &bmData , sizeof(BitmapData) );
bmData.Height = bm.bmHeight;
bmData.Width = bm.bmWidth;
bmData.PixelFormat = pixelFormat;
UINT bitsPerLine = imageInfo.Width * bm.bmBitsPixel;
UINT bitAlignment = sizeof(LONG) * 8;
UINT bitStride = bitAlignment * (bitsPerLine /
bitAlignment); // The image buffer is always padded to LONG
boundaries
if ((bitsPerLine % bitAlignment) != 0)
bitStride += bitAlignment; // Add a bit more for the leftover values
bmData.Stride = bitStride / 8;
RECT rect;
rect.top = 0;
rect.bottom = bm.bmHeight;
rect.left = 0;
rect.right = bm.bmWidth;
if( bm.bmBits )
{
bmData.Scan0 = bm.bmBits;
hRes = pSink->PushPixelData(&rect, &bitmapData, TRUE);
}
else
{
bmData.Scan0 = lpBits;
hRes = pSink->PushPixelData(&rect, &bmData, TRUE);
}
if( !SUCCEEDED( hRes ) )
{
ASSERT( FALSE );
return;
}
free( palette );
VERIFY( SUCCEEDED( pSink->EndSink(S_OK) ) );
pSink->Release();
VERIFY( SUCCEEDED( pEncoder->TerminateEncoder() ) );
//CoUninitialize();
}
.
- Follow-Ups:
- Prev by Date: GetidleTime issues on device
- Next by Date: Re: GetidleTime issues on device
- Previous by thread: GetidleTime issues on device
- Next by thread: Re: How to directly pass bitmap bits into PushPixelData call...
- Index(es):
Relevant Pages
|
Loading