问题
Delphi's TBitmap type is basically a wrapper over a GDI BITMAP and PALETTE, and can support both top-down and bottom-up scanline ordering.
I have a TBitmap which I need to convert to GDI+ Bitmap, in order to rotate and composite it.
My bitmap is 32-bit ARGB, which windows supports, but VCL doesn't natively 'understand'.
TBitmap *bmp;
...
When I use the following constructor, the alpha channel doesn't work for compositing, but otherwise everything works.
Gdiplus::Bitmap b(bmp->Handle, NULL);
So, I tried the constructor below, which takes size, pixel data and format params.
Gdiplus::Bitmap b(bmp->Width, bmp->Height, bmp->Width *4, PixelFormat32bppARGB,
(BYTE*) bmp->ScanLine[bmp->Height-1]); // bottom up storage
This gets the alpha, but the bitmap is upside down, so I tried this
Gdiplus::Bitmap b(bmp->Width, bmp->Height, - bmp->Width *4, PixelFormat32bppARGB,
(BYTE*) bmp->ScanLine[0]); // negative stride for bottom up bitmaps?!
Now, that works, but of course I'm hard-coded into bottom-up bitmaps. However, I can't find a way of determining if the TBitmap is top-down or bottom-up. They're stored internally with negative height but the height value is massaged before it's passed back to user code.
How can I find out the scanline ordering, or - better yet - is there another way of creating a GDIPlus bitmap from a TBitmap?
回答1:
The TBitmap::ScanLine
property accounts for top-down and bottom-up. For a bottom-up bitmap, ScanLine[0]
returns the last row, and ScanLine[Height-1]
returns the first row, of the raw pixel data. For a top-down bitmap, ScanLine[0]
returns the first row, and ScanLine[Height-1]
returns the last row, of the raw pixel data.
To determine if a TBitmap
is bottom-up or top-down, you have to manually retreive its BITMAPINFOHEADER structure, which TBitmap
does not natively expose. You can use the Win32 API GetObject() function to retreive a DIBSECTION structure, which has a BITMAPINFOHEADER member.
来源:https://stackoverflow.com/questions/14368136/delphi-cbuilder-tbitmap-how-to-determinine-scanline-order