You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
518 lines
14 KiB
518 lines
14 KiB
/* $Id: gfxpixelimage.c,v 1.11 2004/09/25 10:57:51 stpohle Exp $ */
|
|
/* gfx pixel manipulation and image manipulation */
|
|
|
|
#include "bomberclone.h"
|
|
|
|
void
|
|
getRGBpixel (SDL_Surface * surface, int x, int y, int *R, int *G, int *B)
|
|
{
|
|
Uint32 pixel = 0;
|
|
Uint8 r,
|
|
g,
|
|
b;
|
|
|
|
/* Lock the screen for direct access to the pixels */
|
|
if (SDL_MUSTLOCK (surface))
|
|
if (SDL_LockSurface (surface) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
return;
|
|
}
|
|
pixel = getpixel (surface, x, y);
|
|
if (SDL_MUSTLOCK (surface)) {
|
|
SDL_UnlockSurface (surface);
|
|
}
|
|
SDL_GetRGB (pixel, surface->format, &r, &g, &b);
|
|
*R = r;
|
|
*G = g;
|
|
*B = b;
|
|
};
|
|
|
|
|
|
/* getpixel for every BPP version */
|
|
Uint32
|
|
getpixel (SDL_Surface * surface, int x, int y)
|
|
{
|
|
int bpp = surface->format->BytesPerPixel;
|
|
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp;
|
|
switch (bpp) {
|
|
case 1:
|
|
return *p;
|
|
case 2:
|
|
return *(Uint16 *) p;
|
|
case 3:
|
|
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
|
return p[0] << 16 | p[1] << 8 | p[2];
|
|
else
|
|
return p[0] | p[1] << 8 | p[2] << 16;
|
|
case 4:
|
|
return *(Uint32 *) p;
|
|
default:
|
|
return 0; /* shouldn't happen, but avoids warnings */
|
|
}
|
|
};
|
|
|
|
|
|
static inline Uint32
|
|
getpixel32 (SDL_Surface * surface, int x, int y)
|
|
{
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
return *(Uint32 *) p;
|
|
};
|
|
|
|
|
|
static inline Uint32
|
|
getpixel24 (SDL_Surface * surface, int x, int y)
|
|
{
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;;
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
return p[0] << 16 | p[1] << 8 | p[2];
|
|
#else
|
|
return p[0] | p[1] << 8 | p[2] << 16;
|
|
#endif
|
|
};
|
|
|
|
|
|
static inline Uint32
|
|
getpixel16 (SDL_Surface * surface, int x, int y)
|
|
{
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
return *(Uint16 *) p;
|
|
};
|
|
|
|
|
|
/* putpixel seperated for every BPP version */
|
|
inline void
|
|
putpixel (SDL_Surface * surface, int x, int y, Uint32 pixel)
|
|
{
|
|
/* Here p is the address to the pixel we want to set */
|
|
int bpp = surface->format->BytesPerPixel;
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp;
|
|
|
|
switch (bpp) {
|
|
case 1:
|
|
*p = pixel;
|
|
break;
|
|
case 2:
|
|
*(Uint16 *) p = pixel;
|
|
break;
|
|
case 3:
|
|
if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
|
p[0] = (pixel >> 16) & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = pixel & 0xff;
|
|
}
|
|
else {
|
|
p[0] = pixel & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = (pixel >> 16) & 0xff;
|
|
}
|
|
break;
|
|
case 4:
|
|
*(Uint32 *) p = pixel;
|
|
break;
|
|
}
|
|
};
|
|
|
|
|
|
static inline void
|
|
putpixel32 (SDL_Surface * surface, int x, int y, Uint32 pixel)
|
|
{
|
|
/* Here p is the address to the pixel we want to set */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
*(Uint32 *) p = pixel;
|
|
};
|
|
|
|
|
|
static inline void
|
|
putpixel24 (SDL_Surface * surface, int x, int y, Uint32 pixel)
|
|
{
|
|
/* Here p is the address to the pixel we want to set */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
p[0] = (pixel >> 16) & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = pixel & 0xff;
|
|
#else
|
|
p[0] = pixel & 0xff;
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
p[2] = (pixel >> 16) & 0xff;
|
|
#endif
|
|
};
|
|
|
|
|
|
static inline void
|
|
putpixel16 (SDL_Surface * surface, int x, int y, Uint32 pixel)
|
|
{
|
|
/* Here p is the address to the pixel we want to set */
|
|
Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
*(Uint16 *) p = pixel;
|
|
};
|
|
|
|
|
|
void
|
|
scale (short int *dpattern, short int x, short int y)
|
|
{
|
|
int a,
|
|
dx,
|
|
dy;
|
|
if (x >= SCALE_MAXRES || y >= SCALE_MAXRES) {
|
|
for (x = 0; x < SCALE_MAXRES; x++)
|
|
dpattern[x] = 0;
|
|
return;
|
|
}
|
|
if (x > y) {
|
|
dy = 2 * y;
|
|
dx = a = 2 * x - dy;
|
|
|
|
do {
|
|
if (a <= 0) {
|
|
dpattern[(y--) - 1] = x;
|
|
a = a + dx;
|
|
}
|
|
|
|
else
|
|
a = a - dy;
|
|
} while (x--);
|
|
}
|
|
|
|
else {
|
|
dy = 2 * x;
|
|
dx = a = 2 * y - dy;
|
|
|
|
do {
|
|
dpattern[y] = x;
|
|
if (a <= 0) {
|
|
x--;
|
|
a = a + dx;
|
|
}
|
|
|
|
else
|
|
a = a - dy;
|
|
} while (y--);
|
|
}
|
|
};
|
|
|
|
|
|
SDL_Surface *
|
|
scale_image (SDL_Surface *orginal, int newx, int newy)
|
|
{
|
|
Uint32 rmask,
|
|
gmask,
|
|
bmask,
|
|
amask;
|
|
SDL_Surface *surface;
|
|
int y,
|
|
x;
|
|
int bpp = orginal->format->BytesPerPixel;
|
|
short int xpattern[SCALE_MAXRES];
|
|
short int ypattern[SCALE_MAXRES];
|
|
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
rmask = 0xff000000;
|
|
gmask = 0x00ff0000;
|
|
bmask = 0x0000ff00;
|
|
amask = 0x000000ff;
|
|
#else /* */
|
|
rmask = 0x000000ff;
|
|
gmask = 0x0000ff00;
|
|
bmask = 0x00ff0000;
|
|
amask = 0xff000000;
|
|
#endif /* */
|
|
|
|
surface = SDL_CreateRGBSurface (SDL_HWSURFACE, newx, newy, 32, rmask, gmask, bmask, amask);
|
|
if (surface == NULL) {
|
|
fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
|
|
/* Lock the screen for direct access to the pixels */
|
|
if (SDL_MUSTLOCK (surface))
|
|
if (SDL_LockSurface (surface) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (orginal))
|
|
if (SDL_LockSurface (orginal) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (surface)) {
|
|
SDL_UnlockSurface (surface);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* do the scaling work */
|
|
scale (xpattern, orginal->w - 1, newx);
|
|
scale (ypattern, orginal->h - 1, newy);
|
|
|
|
switch (bpp) {
|
|
case (2):
|
|
for (x = newx - 1; x >= 0; x--)
|
|
for (y = newy - 1; y >= 0; y--)
|
|
putpixel16 (surface, x, y, getpixel16 (orginal, xpattern[x], ypattern[y]));
|
|
break;
|
|
case (3):
|
|
for (x = newx - 1; x >= 0; x--)
|
|
for (y = newy - 1; y >= 0; y--)
|
|
putpixel24 (surface, x, y, getpixel24 (orginal, xpattern[x], ypattern[y]));
|
|
break;
|
|
case (4):
|
|
for (x = newx - 1; x >= 0; x--)
|
|
for (y = newy - 1; y >= 0; y--)
|
|
putpixel32 (surface, x, y, getpixel32 (orginal, xpattern[x], ypattern[y]));
|
|
break;
|
|
default:
|
|
printf ("scale_image, wrong bpp value (%d).\n", bpp);
|
|
exit (1);
|
|
break;
|
|
}
|
|
|
|
if (SDL_MUSTLOCK (orginal)) {
|
|
SDL_UnlockSurface (orginal);
|
|
}
|
|
if (SDL_MUSTLOCK (surface)) {
|
|
SDL_UnlockSurface (surface);
|
|
}
|
|
return surface;
|
|
};
|
|
|
|
|
|
|
|
SDL_Surface *
|
|
makegray_image (SDL_Surface * org)
|
|
{
|
|
Uint32 rmask,
|
|
gmask,
|
|
bmask,
|
|
amask;
|
|
Uint32 pixel,
|
|
transpixel = 0;
|
|
SDL_Surface *dest;
|
|
int bpp = org->format->BytesPerPixel,
|
|
y,
|
|
x;
|
|
Uint8 r,
|
|
g,
|
|
b,
|
|
gray;
|
|
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
rmask = 0xff000000;
|
|
gmask = 0x00ff0000;
|
|
bmask = 0x0000ff00;
|
|
amask = 0x000000ff;
|
|
#else /* */
|
|
rmask = 0x000000ff;
|
|
gmask = 0x0000ff00;
|
|
bmask = 0x00ff0000;
|
|
amask = 0xff000000;
|
|
#endif /* */
|
|
|
|
dest = SDL_CreateRGBSurface (SDL_SWSURFACE, org->w, org->h, org->format->BitsPerPixel,
|
|
org->format->Rmask, org->format->Gmask,
|
|
org->format->Bmask, org->format->Amask);
|
|
if (dest == NULL) {
|
|
fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
|
|
/* Lock the screen for direct access to the pixels */
|
|
if (SDL_MUSTLOCK (dest))
|
|
if (SDL_LockSurface (dest) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (org))
|
|
if (SDL_LockSurface (org) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
switch (bpp) {
|
|
case (2):
|
|
for (x = 0; x < org->w; x++)
|
|
for (y = 0; y < org->h; y++) {
|
|
pixel = getpixel16 (org, x, y);
|
|
if (x == 0 && y == 0)
|
|
transpixel = pixel;
|
|
if (pixel != transpixel) {
|
|
SDL_GetRGB (pixel, org->format, &r, &g, &b);
|
|
gray = (r / 3 + g / 3 + b / 3);
|
|
pixel = SDL_MapRGB (dest->format, gray, gray, gray);
|
|
}
|
|
putpixel16 (dest, x, y, pixel);
|
|
}
|
|
break;
|
|
case (3):
|
|
for (x = 0; x < org->w; x++)
|
|
for (y = 0; y < org->h; y++) {
|
|
pixel = getpixel24 (org, x, y);
|
|
if (x == 0 && y == 0)
|
|
transpixel = pixel;
|
|
if (pixel != transpixel) {
|
|
SDL_GetRGB (pixel, org->format, &r, &g, &b);
|
|
gray = (r / 3 + g / 3 + b / 3);
|
|
pixel = SDL_MapRGB (dest->format, gray, gray, gray);
|
|
}
|
|
putpixel24 (dest, x, y, pixel);
|
|
}
|
|
break;
|
|
case (4):
|
|
for (x = 0; x < org->w; x++)
|
|
for (y = 0; y < org->h; y++) {
|
|
pixel = getpixel32 (org, x, y);
|
|
if (x == 0 && y == 0)
|
|
transpixel = pixel;
|
|
if (pixel != transpixel) {
|
|
SDL_GetRGB (pixel, org->format, &r, &g, &b);
|
|
gray = (r / 3 + g / 3 + b / 3);
|
|
pixel = SDL_MapRGB (dest->format, gray, gray, gray);
|
|
}
|
|
putpixel32 (dest, x, y, pixel);
|
|
}
|
|
break;
|
|
default:
|
|
printf ("gray_image, wrong bpp value (%d).\n", bpp);
|
|
exit (1);
|
|
break;
|
|
}
|
|
|
|
if (SDL_MUSTLOCK (org)) {
|
|
SDL_UnlockSurface (org);
|
|
}
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
SDL_SetColorKey (dest, SDL_SRCCOLORKEY, transpixel);
|
|
return dest;
|
|
};
|
|
|
|
SDL_Surface *
|
|
gfx_quater_image (SDL_Surface * org1, SDL_Surface * org2, SDL_Surface * org3, SDL_Surface * org4)
|
|
{
|
|
Uint32 pixel;
|
|
SDL_Surface *dest;
|
|
int y,
|
|
x;
|
|
|
|
dest = SDL_CreateRGBSurface (SDL_HWSURFACE, org1->w, org1->h, org1->format->BitsPerPixel,
|
|
org1->format->Rmask, org1->format->Gmask,
|
|
org1->format->Bmask, org1->format->Amask);
|
|
if (dest == NULL) {
|
|
fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
|
|
/* Lock the screen for direct access to the pixels */
|
|
if (SDL_MUSTLOCK (dest))
|
|
if (SDL_LockSurface (dest) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (org1))
|
|
if (SDL_LockSurface (org1) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (org2))
|
|
if (SDL_LockSurface (org2) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (org3))
|
|
if (SDL_LockSurface (org3) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return NULL;
|
|
}
|
|
if (SDL_MUSTLOCK (org4))
|
|
if (SDL_LockSurface (org4) < 0) {
|
|
fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ());
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return NULL;
|
|
}
|
|
for (x = 0; x < org1->w / 2; x++)
|
|
for (y = 0; y < org1->h / 2; y++) {
|
|
pixel = getpixel (org1, x, y);
|
|
putpixel (dest, x, y, pixel);
|
|
}
|
|
for (x = org1->w / 2; x < org1->w; x++)
|
|
for (y = 0; y < org1->h / 2; y++) {
|
|
pixel = getpixel (org2, x, y);
|
|
putpixel (dest, x, y, pixel);
|
|
}
|
|
for (x = 0; x < org1->w / 2; x++)
|
|
for (y = org1->h / 2; y < org1->h; y++) {
|
|
pixel = getpixel (org3, x, y);
|
|
putpixel (dest, x, y, pixel);
|
|
}
|
|
for (x = org1->w / 2; x < org1->w; x++)
|
|
for (y = org1->h / 2; y < org1->h; y++) {
|
|
pixel = getpixel (org4, x, y);
|
|
putpixel (dest, x, y, pixel);
|
|
}
|
|
|
|
if (SDL_MUSTLOCK (org1))
|
|
SDL_UnlockSurface (org1);
|
|
if (SDL_MUSTLOCK (org2))
|
|
SDL_UnlockSurface (org2);
|
|
if (SDL_MUSTLOCK (org3))
|
|
SDL_UnlockSurface (org3);
|
|
if (SDL_MUSTLOCK (org4))
|
|
SDL_UnlockSurface (org4);
|
|
if (SDL_MUSTLOCK (dest)) {
|
|
SDL_UnlockSurface (dest);
|
|
}
|
|
return dest;
|
|
};
|
|
|
|
|
|
/*
|
|
* part of a surface from one to another with the same format
|
|
*/
|
|
SDL_Surface *gfx_copyfrom (SDL_Surface *img, SDL_Rect *wnd) {
|
|
SDL_Surface *res;
|
|
SDL_Rect dest;
|
|
res =
|
|
SDL_CreateRGBSurface (SDL_HWSURFACE, wnd->w, wnd->h, img->format->BitsPerPixel,
|
|
img->format->Rmask, img->format->Gmask,
|
|
img->format->Bmask, img->format->Amask);
|
|
dest.x = 0;
|
|
dest.y = 0;
|
|
dest.w = wnd->w;
|
|
dest.h = wnd->h;
|
|
SDL_BlitSurface (img, wnd, res, &dest);
|
|
return res;
|
|
};
|
|
|
|
|
|
/* restore screen from copy */
|
|
void gfx_restorescreen (SDL_Surface *img, SDL_Rect *wnd)
|
|
{
|
|
SDL_Rect dest;
|
|
|
|
dest.x = 0;
|
|
dest.y = 0;
|
|
dest.w = wnd->w;
|
|
dest.h = wnd->h;
|
|
gfx_blit (img, &dest, gfx.screen, wnd, 0);
|
|
return;
|
|
};
|