mirror of https://github.com/aap/librw.git
image masks and raster fixes
This commit is contained in:
parent
853fa44982
commit
4883b03f2b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
458
src/image.cpp
458
src/image.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue