Add set_tile_type, stretch_tile and free_tile
set_tile_type frees tileset memory not in use for the current tile type (paletted or full color). stretch_tile and free_tile support resizing tiles at run time.
This commit is contained in:
committed by
Pasi Kallinen
parent
1870e5a41b
commit
b2c8d916f6
@@ -18,9 +18,15 @@ struct TileImage {
|
|||||||
|
|
||||||
boolean FDECL(read_tiles, (const char *filename, BOOLEAN_P true_color));
|
boolean FDECL(read_tiles, (const char *filename, BOOLEAN_P true_color));
|
||||||
const struct Pixel *NDECL(get_palette);
|
const struct Pixel *NDECL(get_palette);
|
||||||
|
boolean FDECL(set_tile_type, (BOOLEAN_P true_color));
|
||||||
void NDECL(free_tiles);
|
void NDECL(free_tiles);
|
||||||
const struct TileImage *FDECL(get_tile, (unsigned tile_index));
|
const struct TileImage *FDECL(get_tile, (unsigned tile_index));
|
||||||
|
|
||||||
|
/* For resizing tiles */
|
||||||
|
struct TileImage *FDECL(stretch_tile, (const struct TileImage *,
|
||||||
|
unsigned, unsigned));
|
||||||
|
void FDECL(free_tile, (struct TileImage *));
|
||||||
|
|
||||||
/* Used internally by the tile set code */
|
/* Used internally by the tile set code */
|
||||||
struct TileSetImage {
|
struct TileSetImage {
|
||||||
/* Image data */
|
/* Image data */
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "tileset.h"
|
#include "tileset.h"
|
||||||
|
|
||||||
static void FDECL(get_tile_map, (const char *));
|
static void FDECL(get_tile_map, (const char *));
|
||||||
|
static unsigned FDECL(gcd, (unsigned, unsigned));
|
||||||
static void FDECL(split_tiles, (const struct TileSetImage *));
|
static void FDECL(split_tiles, (const struct TileSetImage *));
|
||||||
static void FDECL(free_image, (struct TileSetImage *));
|
static void FDECL(free_image, (struct TileSetImage *));
|
||||||
|
|
||||||
@@ -100,6 +101,29 @@ error:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free tile memory not required by the chosen display mode */
|
||||||
|
boolean
|
||||||
|
set_tile_type(true_color)
|
||||||
|
boolean true_color;
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if (tiles) {
|
||||||
|
if (true_color) {
|
||||||
|
for (i = 0; i < num_tiles; ++i) {
|
||||||
|
free((genericptr_t) tiles[i].indexes);
|
||||||
|
tiles[i].indexes = NULL;
|
||||||
|
}
|
||||||
|
have_palette = FALSE;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < num_tiles; ++i) {
|
||||||
|
free((genericptr_t) tiles[i].pixels);
|
||||||
|
tiles[i].pixels = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const struct Pixel *
|
const struct Pixel *
|
||||||
get_palette()
|
get_palette()
|
||||||
{
|
{
|
||||||
@@ -155,6 +179,112 @@ unsigned tile_index;
|
|||||||
return &tiles[tile_index];
|
return &tiles[tile_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note that any tile returned by this function must be freed */
|
||||||
|
struct TileImage *
|
||||||
|
stretch_tile(inp_tile, out_width, out_height)
|
||||||
|
const struct TileImage *inp_tile;
|
||||||
|
unsigned out_width, out_height;
|
||||||
|
{
|
||||||
|
unsigned x_scale_inp, x_scale_out, y_scale_inp, y_scale_out;
|
||||||
|
unsigned divisor;
|
||||||
|
unsigned size;
|
||||||
|
struct TileImage *out_tile;
|
||||||
|
unsigned x_inp, y_inp, x2, y2, x_out, y_out;
|
||||||
|
unsigned pos;
|
||||||
|
|
||||||
|
/* Derive the scale factors */
|
||||||
|
divisor = gcd(out_width, inp_tile->width);
|
||||||
|
x_scale_inp = inp_tile->width / divisor;
|
||||||
|
x_scale_out = out_width / divisor;
|
||||||
|
divisor = gcd(out_height, inp_tile->height);
|
||||||
|
y_scale_inp = inp_tile->height / divisor;
|
||||||
|
y_scale_out = out_height / divisor;
|
||||||
|
|
||||||
|
/* Derive the stretched tile */
|
||||||
|
out_tile = (struct TileImage *) alloc(sizeof(struct TileImage));
|
||||||
|
out_tile->width = out_width;
|
||||||
|
out_tile->height = out_height;
|
||||||
|
size = out_width * out_height;
|
||||||
|
if (inp_tile->pixels != NULL) {
|
||||||
|
out_tile->pixels = (struct Pixel *) alloc(size * sizeof(struct Pixel));
|
||||||
|
divisor = x_scale_inp * y_scale_inp;
|
||||||
|
for (y_out = 0; y_out < out_height; ++y_out) {
|
||||||
|
for (x_out = 0; x_out < out_width; ++x_out) {
|
||||||
|
unsigned r, g, b, a;
|
||||||
|
|
||||||
|
/* Derive output pixels by blending input pixels */
|
||||||
|
r = 0;
|
||||||
|
g = 0;
|
||||||
|
b = 0;
|
||||||
|
a = 0;
|
||||||
|
for (y2 = 0; y2 < y_scale_inp; ++y2) {
|
||||||
|
y_inp = (y_out * y_scale_inp + y2) / y_scale_out;
|
||||||
|
for (x2 = 0; x2 < x_scale_inp; ++x2) {
|
||||||
|
x_inp = (x_out * x_scale_inp + x2) / x_scale_out;
|
||||||
|
pos = y_inp * inp_tile->width + x_inp;
|
||||||
|
r += inp_tile->pixels[pos].r;
|
||||||
|
g += inp_tile->pixels[pos].g;
|
||||||
|
b += inp_tile->pixels[pos].b;
|
||||||
|
a += inp_tile->pixels[pos].a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = y_out * out_width + x_out;
|
||||||
|
out_tile->pixels[pos].r = r / divisor;
|
||||||
|
out_tile->pixels[pos].g = g / divisor;
|
||||||
|
out_tile->pixels[pos].b = b / divisor;
|
||||||
|
out_tile->pixels[pos].a = a / divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out_tile->pixels = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the output device uses a palette, we can't blend; just pick
|
||||||
|
a subset of the pixels */
|
||||||
|
if (inp_tile->indexes != NULL) {
|
||||||
|
out_tile->indexes = (unsigned char *) alloc(size);
|
||||||
|
for (y_out = 0; y_out < out_height; ++y_out) {
|
||||||
|
for (x_out = 0; x_out < out_width; ++x_out) {
|
||||||
|
pos = y_out * out_width + x_out;
|
||||||
|
x_inp = x_out * x_scale_inp / x_scale_out;
|
||||||
|
y_inp = y_out * y_scale_inp / y_scale_out;
|
||||||
|
out_tile->indexes[pos] =
|
||||||
|
inp_tile->indexes[y_inp * inp_tile->width + x_inp];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out_tile->indexes = NULL;
|
||||||
|
}
|
||||||
|
return out_tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free a tile returned by stretch_tile */
|
||||||
|
/* Do NOT use this with tiles returned by get_tile */
|
||||||
|
void
|
||||||
|
free_tile(tile)
|
||||||
|
struct TileImage *tile;
|
||||||
|
{
|
||||||
|
if (tile != NULL) {
|
||||||
|
free(tile->indexes);
|
||||||
|
free(tile->pixels);
|
||||||
|
free(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the greatest common divisor */
|
||||||
|
static unsigned
|
||||||
|
gcd(a, b)
|
||||||
|
unsigned a, b;
|
||||||
|
{
|
||||||
|
while (TRUE) {
|
||||||
|
if (b == 0) return a;
|
||||||
|
a %= b;
|
||||||
|
if (a == 0) return b;
|
||||||
|
b %= a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
split_tiles(image)
|
split_tiles(image)
|
||||||
const struct TileSetImage *image;
|
const struct TileSetImage *image;
|
||||||
|
|||||||
Reference in New Issue
Block a user