Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1216 lines (1030 sloc) 24.1 KB
#ifndef com_sleepless_image_cpp
#define com_sleepless_image_cpp
// Copyright 2004 Sleepless Software Inc. All Rights Reserved
extern "C" {
void *ext_image_load(const char *uri, int *w, int *h);
int ext_image_draw(void * src,
int src_x, int src_y, int src_w, int src_h,
int dest_x, int dest_y, int dest_w, int dest_h,
float scale_x, float scale_y,
int pivot_x, int pivot_y, float rotation,
float opacity, float depth
);
};
#if defined(linux) // || (defined(__APPLE__) && defined(__GNUC__))
#include "sdl.cpp"
#endif
#ifdef WIN32
#include "windows.cpp"
#endif
//#include "../3rdparty/jpeg-6b/JPG.cpp"
#include "file.cpp"
#include "str.cpp"
#include "assert.cpp"
// XXX WHY!!!! Can't I put this inside struct Image {} ?
static unsigned char *alphaTable = 0;
struct Image
{
int width;
int height;
int pitch;
unsigned char *bits;
unsigned short transparentColor;
char *fromFile;
void *data;
#if defined(linux) //|| (defined(__APPLE__) && defined(__GNUC__))
SDL_Surface *surf;
#endif
#ifdef WIN32
HDC dc;
HBITMAP bm;
HBITMAP obm;
#endif
// Convert a 16 bit color to 24 bit
static unsigned long c16toc24(unsigned short clr)
{
return ((clr & 0xf800) << 8) | ((clr & 0x07e0) << 5) | ((clr & 0x001f) << 3);
}
// Convert a 24 bit color to 16 bit
static unsigned short c24toc16(unsigned long clr)
{
return (unsigned short)
(
((((clr >> 16) & 0xff) & 0xf8) << 8)
|
((((clr >> 8) & 0xff) & 0xfc) << 3)
|
((((clr ) & 0xff) & 0xf8) >> 3)
);
}
// Return a pointer into the pixel data for a given x,y coord
// Or NULL if the coord is outside the bitmap or there is no bitmap.
unsigned short *pixAddr(int px, int py)
{
if(px < 0)
return 0;
if(py < 0)
return 0;
if(px >= width) // this should catch 'no bitmap' condition
return 0; // as width will be 0.
if(py >= height)
return 0;
return (unsigned short *)(bits + ((py * pitch) + (px * 2)));
}
unsigned long getPixel(int x, int y)
{
unsigned short *pp = pixAddr(x, y);
return c16toc24(*pp);
}
// make transparent color be whatever color is in the bottom-right most pixel
void setTransparentColor()
{
unsigned long n = (height - 1) * pitch;
n += (width - 1) * 2;
transparentColor = *((unsigned short *)(bits + n));
}
unsigned char *createBlank(int _w, int _h)
{
#if defined(__APPLE__)
pitch = _w * 2;
//bits = (unsigned char *)malloc(pitch * _h);
//if( bits ) {
// memset(bits, 0, pitch * _h);
//}
width = _w;
height = _h;
#else
// Create the alpha lookup table if it hasn't been done already.
if(!alphaTable)
{
alphaTable = new unsigned char[32 * 32 * 32];
if(!alphaTable)
return 0;
for(unsigned char s = 0; s < 32; s++)
{
for(unsigned char d = 0; d < 32; d++)
{
for(unsigned char a = 0; a < 32; a += 1)
{
float as = (float)a / 31;
float ad = 1.0f - as;
unsigned char n = (unsigned char)((d * ad) + (s * as));
alphaTable[(s<<10) + (d<<5) + (a<<0)] = n;
}
}
}
}
#if defined(linux) //|| (defined(__APPLE__) && defined(__GNUC__))
Uint32 rmsk, gmsk, bmsk, amsk;
rmsk = 0xf800;
gmsk = 0x07e0;
bmsk = 0x001f;
amsk = 0x0000;
pitch = _w * 2;
bits = (unsigned char *)malloc(pitch * _h);
if(bits)
{
surf = SDL_CreateRGBSurfaceFrom(bits, _w, _h, 16, _w * 2, rmsk, gmsk, bmsk, amsk);
if(surf)
{
fillRect(0, 0, width, height, 0x000000, 1);
width = surf->w;
height = surf->h;
}
else
{
free(bits);
bits = 0;
}
}
#endif
#ifdef WIN32
dc = 0;
bm = 0;
obm = 0;
dc = CreateCompatibleDC(0);
int depth = 16;
bm = makeDIB(_w, _h, depth);
if(bm)
{
obm = (HBITMAP)SelectObject(dc, bm);
width = _w;
height = _h;
BITMAP tbm;
GetObject(bm, sizeof(tbm), (void *)&tbm);
pitch = tbm.bmWidthBytes;
bits = (unsigned char *)tbm.bmBits;
}
#endif
#endif
if(bits)
setTransparentColor();
return bits;
}
// d = opaque user-data pointer
Image(int _w, int _h, void *d)
{
width = 0;
height = 0;
bits = 0;
fromFile = 0;
data = d;
createBlank(_w, _h);
}
int loadPNG(const char *name)
{
#ifdef __APPLE__
int w, h;
data = ext_image_load(name, &w, &h);
if( !data )
return 1;
if(!createBlank(w, h))
return 1;
#endif
return 0;
}
#ifndef __palmos__
/* The only targa formats supported here are uncompressed RGB
images of 24 or 32 bits per pixel. Any alpha info is discarded. */
int loadTGA(const char *name)
{
struct TGAHeader { // typical values for 24bit uncompressed RGB
char idfieldlen; // 0
char colormaptype; // 0
char imagetype; // 2
short colormaporigin; // 0
short colormaplength; // 0
char colormapentrysize; // 0
short imageoriginx; // 0
short imageoriginy; // 0
short width; // width
short height; // height
char bitsperpixel; // 24
char imagedescriptor; // 0
} header;
memset(&header, 0, sizeof(header));
File file(name);
unsigned char *bytes = file.getBytes();
if(!bytes)
return 1;
header.idfieldlen = bytes[0];
header.colormaptype = bytes[1];
header.imagetype = bytes[2];
header.colormaporigin = (short)((bytes[4] << 8) | bytes[3]);
header.colormaplength = (short)((bytes[6] << 8) | bytes[5]);
header.colormapentrysize = bytes[7];
header.imageoriginx = (short)((bytes[9] << 8) | bytes[8]);
header.imageoriginy = (short)((bytes[11] << 8) | bytes[10]);
header.width = (short)((bytes[13] << 10) | bytes[12]);
header.height = (short)((bytes[15] << 10) | bytes[14]);
header.bitsperpixel = bytes[16];
header.imagedescriptor = bytes[17];
if(header.colormaptype != 0)
return 1;
if(header.imagetype != 2)
return 1;
if((header.bitsperpixel != 24) && (header.bitsperpixel != 32))
return 1;
if(header.width == 0)
return 1;
if(header.height == 0)
return 1;
if((header.imagedescriptor & 0x20) != 0) // bit 5, 0 = bottom-up
return 1;
if(!createBlank(header.width, header.height))
return 1;
unsigned char *sbits = bytes + 18 + header.idfieldlen;
unsigned short *dbits;
unsigned short c;
int bpp = header.bitsperpixel;
for(int yy = 0; yy < height; yy++)
{
dbits = (unsigned short *)(bits + ((height - 1 - yy) * pitch));
for(int xx = 0; xx < width; xx++)
{
c = 0;
c |= ((*sbits++) & 0xf8) >> 3;
c |= ((*sbits++) & 0xfc) << 3;
c |= ((*sbits++) & 0xf8) << 8;
if(bpp == 32)
sbits++;
*dbits++ = c;
}
}
setTransparentColor();
return 0;
}
int loadPPM(const char *name)
{
File file(name);
char *bytes = (char *)file.getBytes();
if(!bytes)
return 1;
int w, h, m, l;
if(sscanf(bytes, "P6 %d %d %d\n%n", &w, &h, &m, &l) != 3)
{
/* stupid gimp ppm files put a comment on a second line like
this:
P6
# CREATOR: The GIMP's PNM Filter Version 1.0
48 48
255
*/
if(sscanf(bytes, "P6 #%*[^\n]\n %d %d %d\n%n", &w, &h, &m, &l) != 3)
return 1;
}
if(m >= 256)
return 1;
if(!createBlank(w, h))
return 1;
unsigned char *sbits = (unsigned char *)bytes + l;
unsigned short *dbits;
unsigned short c;
for(int yy = 0; yy < height; yy++)
{
dbits = (unsigned short *)bits + (yy * width);
for(int xx = 0; xx < width; xx++)
{
c = 0;
c |= ((*sbits++) & 0xf8) << 8;
c |= ((*sbits++) & 0xfc) << 3;
c |= ((*sbits++) & 0xf8) >> 3;
*dbits++ = c;
}
}
setTransparentColor();
return 0;
}
int loadBMP(const char *name)
{
#if defined(linux) //|| (defined(__APPLE__) && defined(__GNUC__))
SDL_Surface *bsurf = SDL_LoadBMP(name);
if(bsurf)
{
createBlank(bsurf->w, bsurf->h);
if(width > 0)
{
// copy bmp surf to blank surface
SDL_Rect sr;
sr.x = 0;
sr.y = 0;
sr.w = width;
sr.h = height;
SDL_Rect dr;
dr.x = 0;
dr.y = 0;
dr.w = width; // docs say this is ignored, but it isn't
dr.h = height;
SDL_BlitSurface(bsurf, &sr, surf, &dr);
// dispose of bmp surf
SDL_FreeSurface(bsurf);
// set transp color again
setTransparentColor();
}
}
#if 0
TRACE("bmp surf %s:\n", name);
TRACE(" res: %d x %d\n", surf->w, surf->h);
TRACE(" pitch: %d\n", surf->pitch);
TRACE(" mem: %s\n", surf->flags & SDL_SWSURFACE ? "sys" : "vid");
TRACE(" asyncblit: %s\n", surf->flags & SDL_ASYNCBLIT ? "Y" : "N");
TRACE(" dblbuf: %s\n", surf->flags & SDL_DOUBLEBUF ? "Y" : "N");
TRACE(" fullscr: %s\n", surf->flags & SDL_FULLSCREEN ? "Y" : "N");
TRACE(" sizable: %s\n", surf->flags & SDL_RESIZABLE ? "Y" : "N");
TRACE(" hwaccel: %s\n", surf->flags & SDL_HWACCEL ? "Y" : "N");
TRACE(" clrkey: %s\n", surf->flags & SDL_SRCCOLORKEY ? "Y" : "N");
TRACE(" rleaccel: %s\n", surf->flags & SDL_RLEACCEL ? "Y" : "N");
TRACE(" alphablend: %s\n", surf->flags & SDL_SRCALPHA ? "Y" : "N");
TRACE(" prealloced: %s\n", surf->flags & SDL_PREALLOC ? "Y" : "N");
TRACE(" format:\n");
TRACE(" bitsperpixel: %d\n", surf->format->BitsPerPixel);
TRACE(" bytesperpixel: %d\n", surf->format->BytesPerPixel);
TRACE(" rmask: %x\n", surf->format->Rmask);
TRACE(" gmask: %x\n", surf->format->Gmask);
TRACE(" bmask: %x\n", surf->format->Bmask);
TRACE(" amask: %x\n", surf->format->Amask);
TRACE(" rshift: %x\n", surf->format->Rshift);
TRACE(" gshift: %x\n", surf->format->Gshift);
TRACE(" bshift: %x\n", surf->format->Bshift);
TRACE(" ashift: %x\n", surf->format->Ashift);
TRACE(" rloss: %x\n", surf->format->Rloss);
TRACE(" gloss: %x\n", surf->format->Gloss);
TRACE(" bloss: %x\n", surf->format->Bloss);
TRACE(" aloss: %x\n", surf->format->Aloss);
TRACE(" clrkey: %d\n", surf->format->colorkey);
TRACE(" alpha: %d\n", surf->format->alpha);
#endif
#endif
#ifdef WIN32
dc = 0;
bm = 0;
obm = 0;
int _w, _h;
dc = CreateCompatibleDC(0);
int depth = 16; //GetDeviceCaps(dc, BITSPIXEL);
bm = loadDIB(name, &_w, &_h, depth);
if(bm)
{
obm = (HBITMAP)SelectObject(dc, bm);
width = _w;
height = _h;
BITMAP tbm;
GetObject(bm, sizeof(tbm), (void *)&tbm);
pitch = tbm.bmWidthBytes;
// XXX is this working??
//Apparently not.
// if(pitch & 1)
// pitch++;
bits = (unsigned char *)tbm.bmBits;
setTransparentColor();
}
#endif
return 0;
}
#endif
Image(const char *name)
{
width = 0;
height = 0;
bits = 0;
fromFile = new char[strlen(name) + 1];
if(!fromFile)
return;
strcpy(fromFile, name);
// XXX Get PNG read/write code in here, then ditch everything else.
//int w, h;
#ifdef __APPLE__
data = ext_image_load(name, &width, &height);
//if( !data )
// return;
#else
if(!createBlank(w, h))
return;
if(Str::endsWith(name, ".png"))
{
loadPNG(name);
}
else
if(Str::endsWith(name, ".tga"))
{
loadTGA(name);
}
else
if(Str::endsWith(name, ".ppm"))
{
loadPPM(name);
}
else
if(Str::endsWith(name, ".bmp"))
{
loadBMP(name);
}
#endif
}
~Image()
{
if(width && height)
{
#if defined(linux) //|| (defined(__APPLE__) && defined(__GNUC__))
if(surf)
SDL_FreeSurface(surf);
if(bits)
free(bits);
#endif
#ifdef WIN32
SelectObject(dc, obm);
DeleteObject(bm);
DeleteDC(dc);
#endif
}
if(fromFile)
delete fromFile;
}
// Low level blit.
// Assumes all clipping has been done and all values are valid and sane.
// Called by blit().
void blit_norm(Image *srcimg, int srcx, int srcy, int w, int h, int dstx, int dsty, float a, unsigned long t)
{
#ifdef __APPLE__
ext_image_draw(srcimg->data,
srcx, srcy, w, h,
dstx, dsty, w, h,
1.0, 1.0,
0, 0, 0,
a, 0
);
return;
// draw image part XXX
#endif
int srcpitch = srcimg->pitch / 2; // cause we're using words
int srcadd = srcpitch - w;
if(srcimg->pitch & 1)
srcadd++;
unsigned short *srcbits = (unsigned short *)srcimg->bits;
srcbits += (srcy * srcpitch) + srcx;
int dstpitch = pitch / 2; // cause we're using words
int dstadd = dstpitch - w;
if(pitch & 1)
dstadd++;
unsigned short *dstbits = (unsigned short *)bits;
dstbits += (dsty * dstpitch) + dstx;
// XXX
// On some windows machines (can't reproduce it on my XP laptop)
// the blit is "sheared". It only happens when I blit bitmaps
// with odd widths, like 271 instead of 272.
// I can see how this might happen because I am dividing the
// pitch by 2 and then using that to get srcadd.
// However, the windows docs seem to say that the pitch should always
// be word aligned in the bitmap structure.
// For the time being, I'm just requiring that bitmaps have even
// widths.
// XXX
unsigned short tcolor = srcimg->transparentColor;
int x;
int y = 0;
if(a == 1.0)
{
if(!t)
{
// transparency: no (not masked)
// alpha : no (fully opaque)
while(y < h)
{
x = 0;
while(x < w)
{
*dstbits++ = *srcbits++;
x++;
}
srcbits += srcadd;
dstbits += dstadd;
y++;
}
}
else
{
// transparency: yes (masked)
// alpha : no (fully opaque)
unsigned short sb;
while(y < h)
{
x = 0;
while(x < w)
{
sb = *srcbits++;
if(!t || (sb != tcolor)) // XXX isn't "t" always truthy here?
*dstbits++ = sb;
else
dstbits++;
x++;
}
srcbits += srcadd;
dstbits += dstadd;
y++;
}
}
}
else
{
unsigned long sb;
unsigned long db;
unsigned long sa = (unsigned long)(a * 31);
if(!t)
{
// transparency: no (not masked)
// alpha : yes (semi-transparent)
while(y < h)
{
x = 0;
while(x < w)
{
sb = *srcbits++;
db = *dstbits;
*dstbits++ =
((alphaTable[((sb & 0xf800) >> 1) | ((db & 0xf800) >> 6) | sa]) << 11)
|
((alphaTable[((sb & 0x07c0) << 4) | ((db & 0x07c0) >> 1) | sa]) << 6)
|
((alphaTable[((sb & 0x001f) << 10) | ((db & 0x001f) << 5) | sa]) );
x++;
}
srcbits += srcadd;
dstbits += dstadd;
y++;
}
}
else
{
// transparency: yes (masked)
// alpha : yes (semi-transparent)
while(y < h)
{
x = 0;
while(x < w)
{
sb = *srcbits++;
db = *dstbits;
if(!t || (sb != tcolor))
{
*dstbits++ =
((alphaTable[((sb & 0xf800) >> 1) | ((db & 0xf800) >> 6) | sa]) << 11)
|
((alphaTable[((sb & 0x07c0) << 4) | ((db & 0x07c0) >> 1) | sa]) << 6)
|
((alphaTable[((sb & 0x001f) << 10) | ((db & 0x001f) << 5) | sa]) );
}
else
{
dstbits++;
}
x++;
}
srcbits += srcadd;
dstbits += dstadd;
y++;
}
}
}
}
// XXX 'a' overall alpha value is currently ignored.
void gel_blit_norm(Image *srcimg, int srcx, int srcy, int w, int h, int dstx, int dsty, float a, unsigned long gc)
{
#ifdef __APPLE__
// xxx p_drawImagePart_ext2(srcimg->data, srcx, srcy, w, h, dstx, dsty, a, 0, 0, 0, 1, 1);
ext_image_draw( srcimg->data,
srcx, srcy, w, h,
dstx, dsty, w, h,
1.0, 1.0,
0, 0, 1.0,
a, 0
);
return;
#endif
// Image *dstimg = this;
int srcpitch = srcimg->pitch / 2; // cause we're using words
int srcadd = srcpitch - w;
unsigned short *srcbits = (unsigned short *)srcimg->bits;
srcbits += (srcy * srcpitch) + srcx;
int dstpitch = pitch / 2; // cause we're using words
int dstadd = dstpitch - w;
unsigned short *dstbits = (unsigned short *)bits;
dstbits += (dsty * dstpitch) + dstx;
// unsigned short tcolor = srcimg->transparentColor;
int x;
int y = 0;
unsigned long sb;
unsigned long db;
unsigned long sa;
unsigned short sgc = c24toc16(gc);
while(y < h)
{
x = 0;
while(x < w)
{
sb = *srcbits++;
sa = sb & 0x001f;
if(sa)
{
db = *dstbits;
*dstbits++ =
((alphaTable[((sgc & 0xf800) >> 1) | ((db & 0xf800) >> 6) | sa]) << 11)
|
((alphaTable[((sgc & 0x07c0) << 4) | ((db & 0x07c0) >> 1) | sa]) << 6)
|
((alphaTable[((sgc & 0x001f) << 10) | ((db & 0x001f) << 5) | sa]) );
}
else
{
dstbits++;
}
x++;
}
srcbits += srcadd;
dstbits += dstadd;
y++;
}
}
// clipping version of gel_blit_norm()
void gel_blit(Image *src, int sx, int sy, int w, int h, int dx, int dy, float a, unsigned long clr)
{
// XXX
// XXX duplicate code ... coalesce with clipping from blit()
// XXX
if((width == 0) || (height == 0))
return;
if(a <= 0.0)
return; // completely transparent ... can't even see it!
if(a > 1.0)
a = 1.0;
// clip to src
int sw = src->width;
int sh = src->height;
if(sx < 0)
{
w -= sx;
sx = 0;
}
if(sy < 0)
{
h -= sy;
sy = 0;
}
if((sx + w) >= sw)
{
w = sw - sx;
}
if((sy + h) >= sh)
{
h = sh - sy;
}
if((w < 1) || (h < 1))
return; // totally clipped.
// clip to dest
int dw = width;
int dh = height;
if(dx < 0)
{
w += dx;
sx -= dx;
dx = 0;
}
if(dy < 0)
{
h += dy;
sy -= dy;
dy = 0;
}
if((dx + w) >= dw)
{
w = dw - dx;
}
if((dy + h) >= dh)
{
h = dh - dy;
}
if((w < 1) || (h < 1))
return; // totally clipped
gel_blit_norm(src, sx, sy, w, h, dx, dy, a, clr);
}
void gel_blit(Image *src, int x, int y, float a, unsigned long clr)
{
gel_blit(src, 0, 0, src->width, src->height, x, y, a, clr);
}
// Normally used blit function.
// Clips to src and dst, and ensures valid and sane values before
// doing anything.
// src = the image that will be drawn into this image
// sx, sy = x, y within src of top left rectangle
// w, h = size of the rectangle to draw in pixels
// dx, dy = x, y within dest of top left corner (where the pixel at sx,sy will go)
// a = alpha/transparency
// t = color of pixel to always draw fully transparent (mask color, like in a .gif image)
void blit(Image *src, int sx, int sy, int w, int h, int dx, int dy, float a, unsigned long t)
{
if((width == 0) || (height == 0))
return;
if(a <= 0.0)
return; // completely transparent ... can't even see it!
if(a > 1.0)
a = 1.0;
// clip to src
int sw = src->width;
int sh = src->height;
if(sx < 0)
{
w -= sx;
sx = 0;
}
if(sy < 0)
{
h -= sy;
sy = 0;
}
if((sx + w) >= sw)
{
w = sw - sx;
}
if((sy + h) >= sh)
{
h = sh - sy;
}
if((w < 1) || (h < 1))
return; // totally clipped.
// clip to dest
int dw = width;
int dh = height;
if(dx < 0)
{
w += dx;
sx -= dx;
dx = 0;
}
if(dy < 0)
{
h += dy;
sy -= dy;
dy = 0;
}
if((dx + w) >= dw)
{
w = dw - dx;
}
if((dy + h) >= dh)
{
h = dh - dy;
}
if((w < 1) || (h < 1))
return; // totally clipped
blit_norm(src, sx, sy, w, h, dx, dy, a, t);
}
void blit(Image *src, int x, int y, float a, unsigned long t)
{
blit(src, 0, 0, src->width, src->height, x, y, a, t);
}
void blit(Image *src, int x, int y)
{
blit(src, x, y, 1.0f, 0);
}
void fillRect(int x, int y, int w, int h, unsigned long c, float a)
{
if((width == 0) || (height == 0))
return;
if(a <= 0.0)
return; // completely transparent ... can't even see it!
if(a > 1.0)
a = 1.0;
// clip
if(x < 0)
{
w += x;
x = 0;
}
if(y < 0)
{
h += y;
y = 0;
}
if((x + w) >= width)
{
w = width - x;
}
if((y + h) >= height)
{
h = height - y;
}
if((w < 1) || (h < 1))
return;
rect(x, y, w, h, c, a);
}
void drawRect(int x, int y, int w, int h, unsigned long c, float a)
{
fillRect(x , y , w, 1, c, a); // top
fillRect(x , y + h - 1, w, 1, c, a); // bottom
fillRect(x , y , 1, h, c, a); // left
fillRect(x + w - 1, y , 1, h, c, a); // right
}
void raisedRect(int x, int y, int w, int h, float a)
{
fillRect(x, y, w - 1, 1, 0xffffff, a);
fillRect(x, y, 1, h - 1, 0xffffff, a);
fillRect(x + w - 1, y + 1, 1, h - 1, 0x000000, a);
fillRect(x + 1, y + h - 1, w - 1, 1, 0x000000, a);
}
void sunkenRect(int x, int y, int w, int h, float a)
{
fillRect(x, y, w - 1, 1, 0x000000, a);
fillRect(x, y, 1, h - 1, 0x000000, a);
fillRect(x + w - 1, y + 1, 1, h - 1, 0xffffff, a);
fillRect(x + 1, y + h - 1, w - 1, 1, 0xffffff, a);
}
/////////////////////////////////////////////////////
#ifdef WIN32
HBITMAP makeDIB(int w, int h, int b)
{
HBITMAP bm;
struct
{
BITMAPINFOHEADER bmiHeader;
DWORD rmask;
DWORD gmask;
DWORD bmask;
} bbb;
bbb.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bbb.bmiHeader.biWidth = w;
bbb.bmiHeader.biHeight = h * -1;
bbb.bmiHeader.biPlanes = 1;
bbb.bmiHeader.biBitCount = b;
bbb.bmiHeader.biCompression = BI_BITFIELDS;
bbb.bmiHeader.biSizeImage = 0;
bbb.bmiHeader.biXPelsPerMeter = 0;
bbb.bmiHeader.biYPelsPerMeter = 0;
bbb.bmiHeader.biClrUsed = 0;
bbb.bmiHeader.biClrImportant = 0;
bbb.rmask = 0xf800;
bbb.gmask = 0x07e0;
bbb.bmask = 0x001f;
bm = CreateDIBSection(0, (BITMAPINFO *)&bbb, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
return bm;
}
/* This function loads the bitmap from resource or disk, and than
duplicates it using CreateDIBSection. The duplication
is necessary so that the software blit routines will get a
valid pointer to the image bits when GetObject() is called. */
HBITMAP loadDIB(const char *name, int *wp, int *hp, int d)
{
HBITMAP hbm = Windows::getBitmap(name, wp, hp);
if(hbm == NULL)
return NULL;
HDC hdc1 = CreateCompatibleDC(dc);
SelectObject(hdc1, hbm);
HBITMAP cbm = makeDIB(*wp, *hp, d);
HDC hdc2 = CreateCompatibleDC(hdc1);
SelectObject(hdc2, cbm);
BitBlt(hdc2, 0, 0, *wp, *hp, hdc1, 0, 0, SRCCOPY);
DeleteDC(hdc2);
DeleteDC(hdc1);
DeleteObject(hbm);
return cbm;
}
#endif
void rect(int dstx, int dsty, int w, int h, unsigned long clr, float a)
{
#ifdef __APPLE__
#else
int dstpitch = pitch / 2;
int dstadd = dstpitch - w;
unsigned short *dstbits = (unsigned short *)bits;
dstbits += (dsty * dstpitch) + dstx;
unsigned short c16 = c24toc16(clr);
int x;
int y = 0;
if(a == 1.0)
{
// alpha : no
while(y < h)
{
x = 0;
while(x < w)
{
*dstbits++ = c16;
x++;
}
dstbits += dstadd;
y++;
}
}
else
{
// alpha : yes
unsigned long db;
unsigned long sb = c16;
unsigned long sa = (unsigned long)(a * 31);
while(y < h)
{
x = 0;
while(x < w)
{
db = *dstbits;
*dstbits++ =
((alphaTable[((sb & 0xf800) >> 1) | ((db & 0xf800) >> 6) | sa]) << 11)
|
((alphaTable[((sb & 0x07c0) << 4) | ((db & 0x07c0) >> 1) | sa]) << 6)
|
((alphaTable[((sb & 0x001f) << 10) | ((db & 0x001f) << 5) | sa]) );
x++;
}
dstbits += dstadd;
y++;
}
}
#endif
}
/* Sets a single dot in the bitmap to color 'clr' with opacity 'a'.
Don't use this for drawing more than a few pixels, unless you
don't care about speed. */
void drawPixel(int px, int py, unsigned long clr, float a)
{
#ifdef __APPLE__
#else
unsigned short *dstbits = pixAddr(px, py);
unsigned short c16 = c24toc16(clr);
unsigned long sa = (unsigned long)(a * 31);
unsigned short db;
if(dstbits)
{
if(a >= 1)
{
*dstbits = c16;
}
else
if(a > 0)
{
db = *dstbits;
*dstbits =
((alphaTable[((clr & 0xf800) >> 1) | ((db & 0xf800) >> 6) | sa]) << 11)
|
((alphaTable[((clr & 0x07c0) << 4) | ((db & 0x07c0) >> 1) | sa]) << 6)
|
((alphaTable[((clr & 0x001f) << 10) | ((db & 0x001f) << 5) | sa]) );
}
}
#endif
}
// XXX Use the ddaline.cpp code in lib/misc/
// I think it's cleaner.
// j.h.
void drawLine(int x1, int y1, int x2, int y2, unsigned long clr, float a)
{
int y_unit = 1;
int ydiff = y2 - y1;
if(ydiff < 0)
{
ydiff = -ydiff; // ydiff becomes abs(ydiff)
y_unit = -1;
}
int x_unit = 1;
int xdiff = x2 - x1;
if(xdiff < 0)
{
xdiff = -xdiff; // xdiff becomes abs(xdiff)
x_unit = -1;
}
int px = x1;
int py = y1;
int error_term = 0;
if(xdiff > ydiff)
{
int length = xdiff + 1;
for(int i = 0; i < length; i++)
{
drawPixel(px, py, clr, a);
px += x_unit;
error_term += ydiff;
if(error_term > xdiff)
{
error_term -= xdiff;
py += y_unit;
}
}
}
else
{
int length = ydiff + 1;
for(int i = 0; i < length; i++)
{
drawPixel(px, py, clr, a);
py += y_unit;
error_term += xdiff;
if(error_term > 0)
{
error_term -= ydiff;
px += x_unit;
}
}
}
}
void makeBW()
{
}
};
#endif // com_sleepless_image_cpp