image masks and raster fixes

This commit is contained in:
aap 2020-07-22 13:56:03 +02:00
parent 853fa44982
commit 4883b03f2b
10 changed files with 569 additions and 71 deletions

View File

@ -741,7 +741,7 @@ rasterFromImage(Raster *raster, Image *image)
truecolimg->pixels = image->pixels;
truecolimg->stride = image->stride;
truecolimg->palette = image->palette;
truecolimg->unindex();
truecolimg->unpalettize();
image = truecolimg;
}

View File

@ -371,7 +371,7 @@ rasterFromImage(Raster *raster, Image *image)
truecolimg->pixels = image->pixels;
truecolimg->stride = image->stride;
truecolimg->palette = image->palette;
truecolimg->unindex();
truecolimg->unpalettize();
image = truecolimg;
}
@ -379,34 +379,34 @@ rasterFromImage(Raster *raster, Image *image)
switch(image->depth){
case 32:
#ifdef RW_GLES
conv = conv_RGBA8888_to_RGBA8888;
conv = conv_RGBA8888_from_RGBA8888;
#else
if(raster->format == Raster::C8888)
conv = conv_RGBA8888_to_RGBA8888;
conv = conv_RGBA8888_from_RGBA8888;
else if(raster->format == Raster::C888)
conv = conv_RGB888_to_RGB888;
conv = conv_RGB888_from_RGB888;
else
goto err;
#endif
break;
case 24:
#ifdef RW_GLES
conv = conv_RGB888_to_RGBA8888;
conv = conv_RGB888_from_RGBA8888;
#else
if(raster->format == Raster::C8888)
conv = conv_RGB888_to_RGBA8888;
conv = conv_RGBA8888_from_RGB888;
else if(raster->format == Raster::C888)
conv = conv_RGB888_to_RGB888;
conv = conv_RGB888_from_RGB888;
else
goto err;
#endif
break;
case 16:
#ifdef RW_GLES
conv = conv_RGBA1555_to_RGBA8888;
conv = conv_RGBA8888_from_ARGB1555;
#else
if(raster->format == Raster::C1555)
conv = conv_RGBA1555_to_RGBA5551;
conv = conv_RGBA5551_from_ARGB1555;
else
goto err;
#endif

View File

@ -80,7 +80,7 @@ Shader *currentShader;
static void
printShaderSource(const char **src)
{
int f, l;
int f;
const char *file;
bool printline;
int line = 1;

View File

@ -85,7 +85,7 @@ Image::allocate(void)
}
if(this->palette == nil){
if(this->depth == 4 || this->depth == 8)
this->palette = rwNewT(uint8, (this->depth==4? 16 : 256)*4, MEMDUR_EVENT | ID_IMAGE);
this->palette = rwNewT(uint8, (1 << this->depth)*4, MEMDUR_EVENT | ID_IMAGE);
this->flags |= 2;
}
}
@ -101,6 +101,7 @@ Image::free(void)
rwFree(this->palette);
this->palette = nil;
}
this->flags = 0;
}
void
@ -350,8 +351,6 @@ Image::hasAlpha(void)
{
uint8 ret = 0xFF;
uint8 *pixels = this->pixels;
if(this->depth == 24)
return 0;
if(this->depth == 32){
for(int y = 0; y < this->height; y++){
uint8 *line = pixels;
@ -361,6 +360,18 @@ Image::hasAlpha(void)
}
pixels += this->stride;
}
}else if(this->depth == 24){
return 0;
}else if(this->depth == 16){
for(int y = 0; y < this->height; y++){
uint8 *line = pixels;
for(int x = 0; x < this->width; x++){
ret &= line[1] & 0x80;
line += 2;
}
pixels += this->stride;
}
return ret != 0x80;
}else if(this->depth <= 8){
for(int y = 0; y < this->height; y++){
uint8 *line = pixels;
@ -375,14 +386,92 @@ Image::hasAlpha(void)
}
void
Image::unindex(void)
Image::convertTo32(void)
{
assert(this->pixels);
uint8 *pixels = this->pixels;
int32 newstride = this->width*4;
uint8 *newpixels;
void (*fun)(uint8 *out, uint8 *in) = nil;
switch(this->depth){
case 4:
case 8:
assert(this->palette);
this->unpalettize(true);
return;
case 16:
fun = conv_RGBA8888_from_ARGB1555;
break;
case 24:
fun = conv_RGBA8888_from_RGB888;
break;
default:
return;
}
newpixels = rwNewT(uint8, newstride*this->height, MEMDUR_EVENT | ID_IMAGE);
for(int y = 0; y < this->height; y++){
uint8 *line = pixels;
uint8 *newline = newpixels;
for(int x = 0; x < this->width; x++){
fun(newline, line);
line += this->bpp;
newline += 4;
}
pixels += this->stride;
newpixels += newstride;
}
this->free();
this->depth = 32;
this->bpp = 4;
this->stride = newstride;
this->pixels = nil;
this->palette = nil;
this->setPixels(newpixels);
}
void
Image::palettize(int32 depth)
{
RGBA colors[256];
ColorQuant quant;
uint8 *newpixels;
uint32 newstride;
quant.init();
quant.addImage(this);
assert(depth <= 8);
quant.makePalette(1<<depth, colors);
newstride = this->width;
newpixels = rwNewT(uint8, newstride*this->height, MEMDUR_EVENT | ID_IMAGE);
// TODO: maybe do floyd-steinberg dithering?
quant.matchImage(newpixels, newstride, this);
this->free();
this->depth = depth;
this->bpp = depth < 8 ? 1 : depth/8;
this->stride = newstride;
this->pixels = nil;
this->palette = nil;
this->setPixels(newpixels);
this->allocate();
memcpy(this->palette, colors, 4*(1<<depth));
quant.destroy();
}
void
Image::unpalettize(bool forceAlpha)
{
if(this->depth > 8)
return;
assert(this->pixels);
assert(this->palette);
int32 ndepth = this->hasAlpha() ? 32 : 24;
int32 ndepth = (forceAlpha || this->hasAlpha()) ? 32 : 24;
int32 nstride = this->width*ndepth/8;
uint8 *npixels = rwNewT(uint8, nstride*this->height, MEMDUR_EVENT | ID_IMAGE);
@ -411,14 +500,89 @@ Image::unindex(void)
this->setPixels(npixels);
}
// Copy the biggest channel value to alpha
void
Image::makeMask(void)
{
int32 maxcol;
switch(this->depth){
case 4:
case 8: {
assert(this->palette);
int32 pallen = 1 << this->depth;
for(int32 i = 0; i < pallen; i++){
maxcol = this->palette[i*4+0];
if(this->palette[i*4+1] > maxcol) maxcol = this->palette[i*4+1];
if(this->palette[i*4+2] > maxcol) maxcol = this->palette[i*4+2];
this->palette[i*4+3] = maxcol;
}
break;
}
case 16:
case 24:
this->convertTo32();
// fallthrough
case 32: {
assert(this->pixels);
uint8 *line = this->pixels;
uint8 *p;
for(int32 y = 0; y < this->height; y++){
p = line;
for(int32 x = 0; x < this->width; x++){
maxcol = p[0];
if(p[1] > maxcol) maxcol = p[1];
if(p[2] > maxcol) maxcol = p[2];
p[3] = maxcol;
p += this->bpp;
}
line += this->stride;
}
break;
}
}
}
void
Image::applyMask(Image *mask)
{
if(this->width != mask->width || this->height != mask->height)
return; // TODO: set an error
// we could use alpha with 16 bits but what's the point?
if(mask->depth == 16 || mask->depth == 24)
return;
this->convertTo32();
assert(this->depth == 32);
uint8 *line = this->pixels;
uint8 *mline = mask->pixels;
uint8 *p, *m;
for(int32 y = 0; y < this->height; y++){
p = line;
m = mline;
for(int32 x = 0; x < this->width; x++){
if(mask->depth == 32)
p[3] = m[3];
else if(mask->depth <= 8)
p[3] = mask->palette[m[0]*4+3];
p += this->bpp;
m += mask->bpp;
}
line += this->stride;
mline += mask->stride;
}
}
void
Image::removeMask(void)
{
if(this->depth <= 8){
assert(this->palette);
int32 pallen = 4*(this->depth == 4 ? 16 : 256);
int32 pallen = 4*(1 << this->depth);
for(int32 i = 0; i < pallen; i += 4)
this->palette[i] = 0xFF;
this->palette[i+3] = 0xFF;
return;
}
if(this->depth == 24)
@ -576,6 +740,28 @@ Image::getFilename(const char *name)
return nil;
}
Image*
Image::readMasked(const char *imageName, const char *maskName)
{
Image *img, *mask;
img = read(imageName);
if(img == nil)
return nil;
if(maskName && maskName[0]){
mask = read(maskName);
if(mask == nil)
return img;
mask->makeMask();
int32 origDepth = img->depth;
img->applyMask(mask);
mask->destroy();
if(origDepth <= 8 && img->depth != origDepth)
img->palettize(origDepth);
}
return img;
}
Image*
Image::read(const char *imageName)
{
@ -583,7 +769,7 @@ Image::read(const char *imageName)
char *filename, *ext, *found;
Image *img;
filename = rwNewT(char, strlen(imageName) + 20, MEMDUR_FUNCTION | ID_TEXTURE);
filename = rwNewT(char, strlen(imageName) + 20, MEMDUR_FUNCTION | ID_IMAGE);
strcpy(filename, imageName);
ext = filename + strlen(filename);
*ext++ = '.';
@ -652,4 +838,260 @@ Image::registerModule(void)
Engine::registerPlugin(sizeof(ImageGlobals), ID_IMAGEMODULE, imageOpen, imageClose);
}
/*
* Color Quantization
*/
// An address for a single level is 4 bits.
// Since we have 8 bpp that is 32 bits to address any tree node.
// The lower bits address the higher level tree nodes.
// This is essentially a bit reverse and swizzle.
static uint32
makeTreeAddr(RGBA color)
{
int32 i;
uint32 addr = 0;
uint32 r = 1;
uint32 g = 2;
uint32 b = 4;
uint32 a = 8;
for(i = 0; i < 8; i++){
uint32 mask = 0x80>>i;
if(color.red & mask) addr |= r;
if(color.green & mask) addr |= g;
if(color.blue & mask) addr |= b;
if(color.alpha & mask) addr |= a;
r <<= 4;
g <<= 4;
b <<= 4;
a <<= 4;
}
return addr;
}
void
ColorQuant::Node::destroy(void)
{
int i;
for(i = 0; i < 16; i++)
if(this->children[i])
this->children[i]->destroy();
if(this->link.next)
this->link.remove();
rwFree(this);
}
ColorQuant::Node*
ColorQuant::createNode(int32 level)
{
int i;
ColorQuant::Node *node = rwNewT(ColorQuant::Node, 1, MEMDUR_EVENT | ID_IMAGE);
node->parent = nil;
for(i = 0; i < 16; i++)
node->children[i] = nil;
node->r = 0;
node->g = 0;
node->b = 0;
node->a = 0;
node->numPixels = 0;
node->link.init();
if(level == 0)
this->leaves.append(&node->link);
return node;
}
ColorQuant::Node*
ColorQuant::getNode(ColorQuant::Node *root, uint32 addr, int32 level)
{
if(level == 0)
return root;
uint32 a = addr & 0xF;
if(root->children[a] == nil){
root->children[a] = this->createNode(level-1);
root->children[a]->parent = root;
}
return this->getNode(root->children[a], addr>>4, level-1);
}
ColorQuant::Node*
ColorQuant::findNode(ColorQuant::Node *root, uint32 addr, int32 level)
{
if(level == 0)
return root;
uint32 a = addr & 0xF;
if(root->children[a] == nil)
return root;
return this->findNode(root->children[a], addr>>4, level-1);
}
void
ColorQuant::reduceNode(Node *node)
{
int i;
assert(node->numPixels == 0);
for(i = 0; i < 16; i++)
if(node->children[i]){
node->r += node->children[i]->r;
node->g += node->children[i]->g;
node->b += node->children[i]->b;
node->a += node->children[i]->a;
node->numPixels += node->children[i]->numPixels;
node->children[i]->destroy();
node->children[i] = nil;
}
assert(node->link.next == nil);
assert(node->link.prev == nil);
this->leaves.append(&node->link);
}
void
ColorQuant::Node::addColor(RGBA color)
{
this->r += color.red;
this->g += color.green;
this->b += color.blue;
this->a += color.alpha;
this->numPixels++;
}
void
ColorQuant::init(void)
{
this->leaves.init();
this->root = this->createNode(QUANTDEPTH);
}
void
ColorQuant::destroy(void)
{
this->root->destroy();
}
void
ColorQuant::addColor(RGBA color)
{
uint32 addr = makeTreeAddr(color);
ColorQuant::Node *node = this->getNode(root, addr, QUANTDEPTH);
node->addColor(color);
}
uint8
ColorQuant::findColor(RGBA color)
{
uint32 addr = makeTreeAddr(color);
ColorQuant::Node *node = this->findNode(root, addr, QUANTDEPTH);
return node->numPixels;
}
void
ColorQuant::addImage(Image *img)
{
RGBA col;
uint8 rgba[4];
uint8 *pixels = img->pixels;
for(int y = 0; y < img->height; y++){
uint8 *line = pixels;
for(int x = 0; x < img->width; x++){
uint8 *p = line;
switch(img->depth){
case 4: case 8:
conv_RGBA8888_from_RGBA8888(rgba, &img->palette[p[0]*4]);
break;
case 32:
conv_RGBA8888_from_RGBA8888(rgba, p);
break;
case 24:
conv_RGBA8888_from_RGB888(rgba, p);
break;
case 16:
conv_RGBA8888_from_ARGB1555(rgba, p);
break;
default: assert(0 && "invalid depth");
}
col.red = rgba[0];
col.green = rgba[1];
col.blue = rgba[2];
col.alpha = rgba[3];
this->addColor(col);
line += img->bpp;
}
pixels += img->stride;
}
}
void
ColorQuant::makePalette(int32 numColors, RGBA *colors)
{
while(this->leaves.count() > numColors){
Node *n = LLLinkGetData(this->leaves.link.next, Node, link);
this->reduceNode(n->parent);
}
int i = 0;
FORLIST(lnk, this->leaves){
Node *n = LLLinkGetData(lnk, Node, link);
n->r /= n->numPixels;
n->g /= n->numPixels;
n->b /= n->numPixels;
n->a /= n->numPixels;
colors[i].red = n->r;
colors[i].green = n->g;
colors[i].blue = n->b;
colors[i].alpha = n->a;
n->numPixels = i++;
}
}
void
ColorQuant::matchImage(uint8 *dstPixels, uint32 dstStride, Image *img)
{
RGBA col;
uint8 rgba[4];
uint8 *pixels = img->pixels;
for(int y = 0; y < img->height; y++){
uint8 *line = pixels;
uint8 *dline = dstPixels;
for(int x = 0; x < img->width; x++){
uint8 *p = line;
uint8 *d = dline;
switch(img->depth){
case 4: case 8:
conv_RGBA8888_from_RGBA8888(rgba, &img->palette[p[0]*4]);
break;
case 32:
conv_RGBA8888_from_RGBA8888(rgba, p);
break;
case 24:
conv_RGBA8888_from_RGB888(rgba, p);
break;
case 16:
conv_RGBA8888_from_ARGB1555(rgba, p);
break;
default: assert(0 && "invalid depth");
}
col.red = rgba[0];
col.green = rgba[1];
col.blue = rgba[2];
col.alpha = rgba[3];
*d = this->findColor(col);
line += img->bpp;
dline++;
}
pixels += img->stride;
dstPixels += dstStride;
}
}
}

View File

@ -1566,31 +1566,31 @@ rasterUnlockPalette(Raster *raster)
}
void
expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
expandPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++){
dst[y*w + x*2 + 0] = src[y*srcw/2 + x] & 0xF;
dst[y*w + x*2 + 1] = src[y*srcw/2 + x] >> 4;
dst[y*dststride + x*2 + 0] = src[y*srcstride + x] & 0xF;
dst[y*dststride + x*2 + 1] = src[y*srcstride + x] >> 4;
}
}
void
compressPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
compressPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++)
dst[y*srcw/2 + x] = src[y*w + x*2 + 0] | src[y*w + x*2 + 1] << 4;
dst[y*dststride + x] = src[y*srcstride + x*2 + 0] | src[y*srcstride + x*2 + 1] << 4;
}
void
copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
copyPSMT8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
dst[y*w + x] = src[y*srcw + x];
dst[y*dststride + x] = src[y*srcstride + x];
}
// Almost the same as d3d9 and gl3 function
@ -1691,23 +1691,22 @@ rasterFromImage(Raster *raster, Image *image)
int tw;
transferMinSize(image->depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
tw = max(image->width, minw);
in = image->pixels;
uint8 *src = image->pixels;
out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(image->depth == 4){
compressPSMT4(out, in, image->width, image->height, tw);
compressPSMT4(out, tw/2, src, image->stride, image->width, image->height);
}else if(image->depth == 8){
copyPSMT8(out, in, image->width, image->height, tw);
copyPSMT8(out, tw, src, image->stride, image->width, image->height);
}else{
// TODO: stride
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
for(int32 y = 0; y < image->height; y++){
in = src;
for(int32 x = 0; x < image->width; x++){
switch(raster->format & 0xF00){
case Raster::C8888:
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = in[3]*128/255;
in += 4;
out += 4;
break;
case Raster::C888:
@ -1715,19 +1714,20 @@ rasterFromImage(Raster *raster, Image *image)
out[1] = in[1];
out[2] = in[2];
out[3] = 0x80;
in += 3;
out += 4;
break;
case Raster::C1555:
out[0] = in[0];
out[1] = in[1];
in += 2;
conv_ARGB1555_from_ABGR1555(out, in);
out += 2;
break;
default:
assert(0 && "unknown ps2 raster format");
break;
}
in += image->bpp;
}
src += image->stride;
}
}
raster->unlock(0);
return 1;
@ -1792,16 +1792,16 @@ rasterToImage(Raster *raster)
int tw;
transferMinSize(depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
tw = max(raster->width, minw);
out = image->pixels;
uint8 *dst = image->pixels;
in = raster->lock(0, Raster::LOCKREAD);
if(depth == 4){
expandPSMT4(out, in, raster->width, raster->height, tw);
expandPSMT4(dst, image->stride, in, tw/2, raster->width, raster->height);
}else if(depth == 8){
copyPSMT8(out, in, raster->width, raster->height, tw);
}else
// TODO: stride
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
copyPSMT8(dst, image->stride, in, tw, raster->width, raster->height);
}else{
for(int32 y = 0; y < image->height; y++){
out = dst;
for(int32 x = 0; x < image->width; x++){
switch(raster->format & 0xF00){
case Raster::C8888:
out[0] = in[0];
@ -1809,31 +1809,31 @@ rasterToImage(Raster *raster)
out[2] = in[2];
out[3] = in[3]*255/128;
in += 4;
out += 4;
break;
case Raster::C888:
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
in += 4;
out += 3;
break;
case Raster::C1555:
out[0] = in[0];
out[1] = in[1];
conv_ARGB1555_from_ABGR1555(out, in);
in += 2;
out += 2;
break;
case Raster::C555:
out[0] = in[0];
out[1] = in[1] | 0x80;
conv_ARGB1555_from_ABGR1555(out, in);
out[1] |= 0x80;
in += 2;
out += 2;
break;
default:
assert(0 && "unknown ps2 raster format");
break;
}
out += image->bpp;
}
dst += image->stride;
}
}
raster->unlock(0);
return image;

View File

@ -223,8 +223,9 @@ Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
void expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw);
void copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw);
void expandPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void compressPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void copyPSMT8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
}
}

View File

@ -222,7 +222,7 @@ Raster::renderFast(int32 x, int32 y)
}
void
conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in)
conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in)
{
out[0] = in[0];
out[1] = in[1];
@ -231,7 +231,7 @@ conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in)
}
void
conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in)
conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in)
{
out[0] = in[0];
out[1] = in[1];
@ -240,7 +240,7 @@ conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in)
}
void
conv_RGB888_to_RGB888(uint8 *out, uint8 *in)
conv_RGB888_from_RGB888(uint8 *out, uint8 *in)
{
out[0] = in[0];
out[1] = in[1];
@ -248,7 +248,7 @@ conv_RGB888_to_RGB888(uint8 *out, uint8 *in)
}
void
conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in)
conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in)
{
uint32 r, g, b, a;
a = (in[1]>>7) & 1;
@ -260,7 +260,7 @@ conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in)
}
void
conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in)
conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in)
{
uint32 r, g, b, a;
a = (in[1]>>7) & 1;
@ -273,4 +273,14 @@ conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in)
out[3] = a*0xFF;
}
void
conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in)
{
uint32 r, b;
r = (in[1]>>2) & 0x1F;
b = in[0] & 0x1F;
out[1] = in[1]&0x83 | b<<2;
out[0] = in[0]&0xE0 | r;
}
}

View File

@ -142,7 +142,11 @@ struct Image
void setPixelsDXT(int32 type, uint8 *pixels);
void setPalette(uint8 *palette);
bool32 hasAlpha(void);
void unindex(void);
void convertTo32(void);
void palettize(int32 depth);
void unpalettize(bool forceAlpha = false);
void makeMask(void);
void applyMask(Image *mask);
void removeMask(void);
Image *extractMask(void);
@ -150,6 +154,7 @@ struct Image
static void printSearchPath(void);
static char *getFilename(const char*);
static Image *read(const char *imageName);
static Image *readMasked(const char *imageName, const char *maskName);
typedef Image *(*fileRead)(const char *afilename);
@ -166,6 +171,38 @@ void writeTGA(Image *image, const char *filename);
Image *readBMP(const char *filename);
void writeBMP(Image *image, const char *filename);
enum { QUANTDEPTH = 8 };
struct ColorQuant
{
struct Node {
uint32 r, g, b, a;
int32 numPixels;
Node *parent;
Node *children[16];
LLLink link;
void destroy(void);
void addColor(RGBA color);
bool isLeaf(void) { for(int32 i = 0; i < 16; i++) if(this->children[i]) return false; return true; }
};
Node *root;
LinkList leaves;
void init(void);
void destroy(void);
Node *createNode(int32 level);
Node *getNode(Node *root, uint32 addr, int32 level);
Node *findNode(Node *root, uint32 addr, int32 level);
void reduceNode(Node *node);
void addColor(RGBA color);
uint8 findColor(RGBA color);
void addImage(Image *img);
void makePalette(int32 numColors, RGBA *colors);
void matchImage(uint8 *dstPixels, uint32 dstStride, Image *src);
};
// used to emulate d3d and xbox textures
struct RasterLevels
{
@ -265,11 +302,13 @@ struct Raster
};
};
void conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in);
void conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in);
void conv_RGB888_to_RGB888(uint8 *out, uint8 *in);
void conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in);
void conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in);
void conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in);
void conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in);
void conv_RGB888_from_RGB888(uint8 *out, uint8 *in);
void conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in);
void conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in);
void conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in);
inline void conv_ARGB1555_from_ABGR1555(uint8 *out, uint8 *in) { conv_ABGR1555_from_ARGB1555(out, in); }
#define IGNORERASTERIMP 0

View File

@ -299,14 +299,13 @@ defaultFindCB(const char *name)
}
// TODO: actually read the mask!
static Texture*
defaultReadCB(const char *name, const char *mask)
{
Texture *tex;
Image *img;
img = Image::read(name);
img = Image::readMasked(name, mask);
if(img){
tex = Texture::create(Raster::createFromImage(img));
strncpy(tex->name, name, 32);

View File

@ -27,6 +27,9 @@ void genIm3DEnd(void);
void initFont(void);
void printScreen(const char *s, float x, float y);
void initsplines(void);
void rendersplines(void);
rw::Charset *testfont;
//#include <Windows.h>
@ -236,7 +239,7 @@ InitRW(void)
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
camera->m_rwcam = Scene.camera;
camera->m_aspectRatio = 640.0f/448.0f;
camera->m_near = 5.0f;
camera->m_near = 0.5f;
// camera->m_far = 450.0f;
camera->m_far = 15.0f;
camera->m_target.set(0.0f, 0.0f, 0.0f);
@ -248,6 +251,8 @@ InitRW(void)
Scene.world->addCamera(camera->m_rwcam);
initsplines();
return true;
}
@ -382,7 +387,7 @@ Draw(float timeDelta)
{
getFrontBuffer();
static rw::RGBA clearcol = { 0x60, 0x60, 0x60, 0xFF };
static rw::RGBA clearcol = { 161, 161, 161, 0xFF };
camera->m_rwcam->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
camera->update();
camera->m_rwcam->beginUpdate();
@ -401,10 +406,12 @@ extern void endSoftras(void);
// im2dtest();
// Scene.clump->render();
im3dtest();
// im3dtest();
// printScreen("Hello, World!", 10, 10);
testfont->print("foo ABC", 200, 200, true);
// testfont->print("foo ABC", 200, 200, true);
rendersplines();
camera->m_rwcam->endUpdate();