📄 bitmap.h
字号:
The Bitmap contains one or two pixel-sets representing an image. The "primary" is
a fast-blitting version of the image, and the "secondary" is a storage version
(eventually wavelet compressed) which can be used to rebuild the primary if it is
freed or damaged. Both cary a generalized format.
Let's do an example. I want to load a bitmap, set it up for drawing with the
genesis Engine, and then blit some interactive stuff into it.
************************************************************************/
#if 0
// {
//-----------------------------------------------------------------------------
void Init(geEngine * Engine);
void Shutdown(void);
void Draw(void);
void DrawPolite(void);
static geBitmap * myBM = NULL;
static geEngine * myEngine = NULL;
void Init(geEngine * Engine)
{
geBoolean success;
geBitmap_Info Info;
myEngine = Engine; // this is not looked well upon; for ease of demonstration only!
assert(Engine);
myBM = geBitmap_CreateFromFileName(NULL,"mybitmap.bmp");
// CreateFromFile can load windows BMP files, or custom GeBm files.
assert(myBM);
// get the main info; I don't care about the secondary, so leave it NULL
success = geBitmap_GetInfo(myBM,&Info,NULL);
assert(success);
// make sure I loaded a bitmap in the format I understand !
if ( Info.Format == GE_PIXELFORMAT_8BIT_PAL )
{
// I want palette index 255 to act as transparency, so I must use SetColorKey
success = geBitmap_SetColorKey(myBM,GE_TRUE,255);
assert(success);
// just for fun, let's modify the palette:
if (1)
{
geBitmap_Palette * Pal;
// get the palette ; I don't care if its primary or secondary, so
/// I don't use the Info.Palette field
Pal = geBitmap_GetPalette(myBM);
assert(Pal);
// I'm only fiddling one entry, so don't bother with a full Lock() UnLock()
// sequence on the palette
// make palette index zero bright red; we use alpha = 255 for opaque
success = geBitmap_Palette_SetEntryColor(Pal,0,255,0,0,255);
assert(success);
// tell the bitmap system you've changed the palette; this function
// is smart enough to not do unecessary copies or whatever.
success = geBitmap_SetPalette(myBM,Pal);
assert(success);
}
}
else
{
// otherwise, treat black as transparent, in whatever format I have
success = geBitmap_SetColorKey(myBM,GE_TRUE,gePixelFormat_ComposePixel(Info.Format,0,0,0,0));
assert(success);
}
// note that I did NOT use SetFormat. SetFormat may do a conversion, and since the original
// bitmap was created without colorkey, it would have been converted to a new format but
// kept its property of having no colorkey!
// (SetFormat will fiddle the bits and whatever way necessary to keep bitmaps as visually similar
// as possible)
// I want to fiddle the fast format in 565 later, so cue the bitmap to try to give me that format.
success = geBitmap_SetPreferredFormat(myBM,GE_PIXELFORMAT_16BIT_565_RGB);
assert(success);
// Add it to the engine so it can be used for drawing.
success = geEngine_AddBitmap(myEngine,myBM);
assert(success);
}
void Shutdown(void)
{
geBoolean WasDestroyed;
assert(myBM);
// clean up
geEngine_RemoveBitmap(myEngine,myBM);
WasDestroyed = geBitmap_Destroy(&myBM);
// someone else might have done _CreateRef on our bitmap,
// so we can't be sure it's actually destroyed.
// this code is still ready to be run again with a new call to Init()
//assert(WasDestroyed);
myBM = NULL;
myEngine = NULL;
}
void Draw(void)
{
geBitmap * Lock;
geBoolean success;
geBitmap_Info Info;
uint16 *bits,*bptr;
int x,y;
// lets fiddle the bits.
// we need to lock the bitmap for write.
// LockForWrite is an exclusive lock, unlike LockForRead which is non-blocking
// request our favorite format, and only lock Mip 0 (the full size bitmap)
success = geBitmap_LockForWriteFormat(myBM,&Lock,0,0,GE_PIXELFORMAT_16BIT_565_RGB);
if ( ! success )
{
// well, we tried to be nice; if we were very polite, we would do a LockForWrite
// here, and try to fiddle the bits in whatever format we got; However, we aren't
// that polite, so we just do a _SetFormat
//
// note that we are destroying the original bitmap by changing its format
// we should only do this if we are going to draw into the bitmap
success = geBitmap_SetFormat(myBM,GE_PIXELFORMAT_16BIT_565_RGB,GE_TRUE,0,NULL);
assert(success);
// now we should be able to get the bits we want, *but* they may not be the
// primary (fast) format; oh well, it's the best we can do...
// (if you must have the fastest bits, then use only _LockForWrite, never LockForWriteFormat,
// which might have to do a conversion)
success = geBitmap_LockForWriteFormat(myBM,&Lock,0,0,GE_PIXELFORMAT_16BIT_565_RGB);
assert(success);
}
// now Lock is our bitmap in 565
// we do a GetInfo because the Lock's info could be different than
// the original bitmap's (particularly the Palette & the Stride)
success = geBitmap_GetInfo(Lock,&Info,NULL);
assert(success);
// you can only call _GetBits on a locked bitmap
bits = geBitmap_GetBits(Lock);
assert( bits );
bptr = bits;
for(y=0; y < Info.Height; y++)
{
for(x=0; x < Info.Width; x++)
{
uint16 R,G,B;
// make a silly 565 gradient
R = x & 0x1F;
G = x & 0x3F;
B = y & 0x1F;
*bptr++ = (R<<11) + (G<<5) + B;
}
// note that bptr is a word pointer, and Stride is in pixels :
bptr += Info.Stride - Info.Width;
}
bits = bptr = NULL;
// you call Unlock on all the mips you locked - not on the original bitmap!
success = geBitmap_UnLock(Lock);
assert(success);
// now, we only fiddled the full-size Mip, and there might be more,
// so lets percolate the changes into the smaller mips:
success = geBitmap_RefreshMips(myBM);
assert(success);
// a null rect means use the whole bitmap;
// Engine_DrawBitmap blits a 2d decal to the framebuffer (fast)
success = geEngine_DrawBitmap(myEngine,myBM,NULL,0,0);
assert(success);
}
void DrawPolite(void)
{
geBitmap * Lock;
geBoolean success;
geBitmap_Info Info;
void *bits;
int x,y;
// this function does the same thing as Draw() , but is more polite
// lock in the fastest format (whatever it is)
// because we did SetPreferred, this should be 565_RGB, but might not be
success = geBitmap_LockForWrite(myBM,&Lock,0,0);
assert(success);
success = geBitmap_GetInfo(Lock,&Info,NULL);
assert(success);
bits = geBitmap_GetBits(Lock);
assert( bits );
if ( Info.Format == GE_PIXELFORMAT_16BIT_565_RGB )
{
uint16 *wptr;
// our favorite format
wptr = bits;
for(y=0; y < Info.Height; y++)
{
for(x=0; x < Info.Width; x++)
{
uint16 R,G,B;
// make a silly 565 gradient
R = x & 0x1F;
G = x & 0x3F;
B = y & 0x1F;
*wptr++ = (R<<11) + (G<<5) + B;
}
wptr += Info.Stride - Info.Width;
}
}
else
{
uint8 * bptr;
// oh well, do our best
// bitmaps must have had a good reason to not give us the format we preferred,
bptr = bits;
for(y=0; y < Info.Height; y++)
{
for(x=0; x < Info.Width; x++)
{
uint32 R,G,B;
// put a color in any format
R = (x & 0x1F)<<3;
G = (x & 0x3F)<<2;
B = (y & 0x1F)<<3;
// we use alpha of 255 for opaque
gePixelFormat_PutColor(Info.Format,&bptr,R,G,B,255);
}
bptr += (Info.Stride - Info.Width) * gePixelFormat_BytesPerPel(Info.Format);
}
}
bits = NULL;
// same as before:
success = geBitmap_UnLock(Lock);
assert(success);
success = geBitmap_RefreshMips(myBM);
assert(success);
success = geEngine_DrawBitmap(myEngine,myBM,NULL,0,0);
assert(success);
}
// end tutorial on the Bitmap system
//-----------------------------------------------------------------------------
// }
/***********************************************************************************/
#endif
#ifdef __cplusplus
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -