mirror of
				https://github.com/aap/librw.git
				synced 2025-11-04 00:41:59 +00:00 
			
		
		
		
	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->pixels = image->pixels;
 | 
				
			||||||
		truecolimg->stride = image->stride;
 | 
							truecolimg->stride = image->stride;
 | 
				
			||||||
		truecolimg->palette = image->palette;
 | 
							truecolimg->palette = image->palette;
 | 
				
			||||||
		truecolimg->unindex();
 | 
							truecolimg->unpalettize();
 | 
				
			||||||
		image = truecolimg;
 | 
							image = truecolimg;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -371,7 +371,7 @@ rasterFromImage(Raster *raster, Image *image)
 | 
				
			|||||||
		truecolimg->pixels = image->pixels;
 | 
							truecolimg->pixels = image->pixels;
 | 
				
			||||||
		truecolimg->stride = image->stride;
 | 
							truecolimg->stride = image->stride;
 | 
				
			||||||
		truecolimg->palette = image->palette;
 | 
							truecolimg->palette = image->palette;
 | 
				
			||||||
		truecolimg->unindex();
 | 
							truecolimg->unpalettize();
 | 
				
			||||||
		image = truecolimg;
 | 
							image = truecolimg;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -379,34 +379,34 @@ rasterFromImage(Raster *raster, Image *image)
 | 
				
			|||||||
	switch(image->depth){
 | 
						switch(image->depth){
 | 
				
			||||||
	case 32:
 | 
						case 32:
 | 
				
			||||||
#ifdef RW_GLES
 | 
					#ifdef RW_GLES
 | 
				
			||||||
		conv = conv_RGBA8888_to_RGBA8888;
 | 
							conv = conv_RGBA8888_from_RGBA8888;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
		if(raster->format == Raster::C8888)
 | 
							if(raster->format == Raster::C8888)
 | 
				
			||||||
			conv = conv_RGBA8888_to_RGBA8888;
 | 
								conv = conv_RGBA8888_from_RGBA8888;
 | 
				
			||||||
		else if(raster->format == Raster::C888)
 | 
							else if(raster->format == Raster::C888)
 | 
				
			||||||
			conv = conv_RGB888_to_RGB888;
 | 
								conv = conv_RGB888_from_RGB888;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 24:
 | 
						case 24:
 | 
				
			||||||
#ifdef RW_GLES
 | 
					#ifdef RW_GLES
 | 
				
			||||||
		conv = conv_RGB888_to_RGBA8888;
 | 
							conv = conv_RGB888_from_RGBA8888;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
		if(raster->format == Raster::C8888)
 | 
							if(raster->format == Raster::C8888)
 | 
				
			||||||
			conv = conv_RGB888_to_RGBA8888;
 | 
								conv = conv_RGBA8888_from_RGB888;
 | 
				
			||||||
		else if(raster->format == Raster::C888)
 | 
							else if(raster->format == Raster::C888)
 | 
				
			||||||
			conv = conv_RGB888_to_RGB888;
 | 
								conv = conv_RGB888_from_RGB888;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
#ifdef RW_GLES
 | 
					#ifdef RW_GLES
 | 
				
			||||||
		conv = conv_RGBA1555_to_RGBA8888;
 | 
							conv = conv_RGBA8888_from_ARGB1555;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
		if(raster->format == Raster::C1555)
 | 
							if(raster->format == Raster::C1555)
 | 
				
			||||||
			conv = conv_RGBA1555_to_RGBA5551;
 | 
								conv = conv_RGBA5551_from_ARGB1555;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ Shader *currentShader;
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
printShaderSource(const char **src)
 | 
					printShaderSource(const char **src)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int f, l;
 | 
						int f;
 | 
				
			||||||
	const char *file;
 | 
						const char *file;
 | 
				
			||||||
	bool printline;
 | 
						bool printline;
 | 
				
			||||||
	int line = 1;
 | 
						int line = 1;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										458
									
								
								src/image.cpp
									
									
									
									
									
								
							
							
						
						
									
										458
									
								
								src/image.cpp
									
									
									
									
									
								
							@ -85,7 +85,7 @@ Image::allocate(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if(this->palette == nil){
 | 
						if(this->palette == nil){
 | 
				
			||||||
		if(this->depth == 4 || this->depth == 8)
 | 
							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;
 | 
							this->flags |= 2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -101,6 +101,7 @@ Image::free(void)
 | 
				
			|||||||
		rwFree(this->palette);
 | 
							rwFree(this->palette);
 | 
				
			||||||
		this->palette = nil;
 | 
							this->palette = nil;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						this->flags = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@ -350,8 +351,6 @@ Image::hasAlpha(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	uint8 ret = 0xFF;
 | 
						uint8 ret = 0xFF;
 | 
				
			||||||
	uint8 *pixels = this->pixels;
 | 
						uint8 *pixels = this->pixels;
 | 
				
			||||||
	if(this->depth == 24)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	if(this->depth == 32){
 | 
						if(this->depth == 32){
 | 
				
			||||||
		for(int y = 0; y < this->height; y++){
 | 
							for(int y = 0; y < this->height; y++){
 | 
				
			||||||
			uint8 *line = pixels;
 | 
								uint8 *line = pixels;
 | 
				
			||||||
@ -361,6 +360,18 @@ Image::hasAlpha(void)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			pixels += this->stride;
 | 
								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){
 | 
						}else if(this->depth <= 8){
 | 
				
			||||||
		for(int y = 0; y < this->height; y++){
 | 
							for(int y = 0; y < this->height; y++){
 | 
				
			||||||
			uint8 *line = pixels;
 | 
								uint8 *line = pixels;
 | 
				
			||||||
@ -375,14 +386,92 @@ Image::hasAlpha(void)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
						if(this->depth > 8)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	assert(this->pixels);
 | 
						assert(this->pixels);
 | 
				
			||||||
	assert(this->palette);
 | 
						assert(this->palette);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int32 ndepth = this->hasAlpha() ? 32 : 24;
 | 
						int32 ndepth = (forceAlpha || this->hasAlpha()) ? 32 : 24;
 | 
				
			||||||
	int32 nstride = this->width*ndepth/8;
 | 
						int32 nstride = this->width*ndepth/8;
 | 
				
			||||||
	uint8 *npixels = rwNewT(uint8, nstride*this->height, MEMDUR_EVENT | ID_IMAGE);
 | 
						uint8 *npixels = rwNewT(uint8, nstride*this->height, MEMDUR_EVENT | ID_IMAGE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -411,14 +500,89 @@ Image::unindex(void)
 | 
				
			|||||||
	this->setPixels(npixels);
 | 
						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
 | 
					void
 | 
				
			||||||
Image::removeMask(void)
 | 
					Image::removeMask(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(this->depth <= 8){
 | 
						if(this->depth <= 8){
 | 
				
			||||||
		assert(this->palette);
 | 
							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)
 | 
							for(int32 i = 0; i < pallen; i += 4)
 | 
				
			||||||
			this->palette[i] = 0xFF;
 | 
								this->palette[i+3] = 0xFF;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(this->depth == 24)
 | 
						if(this->depth == 24)
 | 
				
			||||||
@ -576,6 +740,28 @@ Image::getFilename(const char *name)
 | 
				
			|||||||
	return nil;
 | 
						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*
 | 
				
			||||||
Image::read(const char *imageName)
 | 
					Image::read(const char *imageName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -583,7 +769,7 @@ Image::read(const char *imageName)
 | 
				
			|||||||
	char *filename, *ext, *found;
 | 
						char *filename, *ext, *found;
 | 
				
			||||||
	Image *img;
 | 
						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);
 | 
						strcpy(filename, imageName);
 | 
				
			||||||
	ext = filename + strlen(filename);
 | 
						ext = filename + strlen(filename);
 | 
				
			||||||
	*ext++ = '.';
 | 
						*ext++ = '.';
 | 
				
			||||||
@ -652,4 +838,260 @@ Image::registerModule(void)
 | 
				
			|||||||
	Engine::registerPlugin(sizeof(ImageGlobals), ID_IMAGEMODULE, imageOpen, imageClose);
 | 
						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
 | 
					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;
 | 
						int32 x, y;
 | 
				
			||||||
	for(y = 0; y < h; y++)
 | 
						for(y = 0; y < h; y++)
 | 
				
			||||||
		for(x = 0; x < w/2; x++){
 | 
							for(x = 0; x < w/2; x++){
 | 
				
			||||||
			dst[y*w + x*2 + 0] = src[y*srcw/2 + x] & 0xF;
 | 
								dst[y*dststride + x*2 + 0] = src[y*srcstride + x] & 0xF;
 | 
				
			||||||
			dst[y*w + x*2 + 1] = src[y*srcw/2 + x] >> 4;
 | 
								dst[y*dststride + x*2 + 1] = src[y*srcstride + x] >> 4;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void
 | 
					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;
 | 
						int32 x, y;
 | 
				
			||||||
	for(y = 0; y < h; y++)
 | 
						for(y = 0; y < h; y++)
 | 
				
			||||||
		for(x = 0; x < w/2; x++)
 | 
							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
 | 
					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;
 | 
						int32 x, y;
 | 
				
			||||||
	for(y = 0; y < h; y++)
 | 
						for(y = 0; y < h; y++)
 | 
				
			||||||
		for(x = 0; x < w; x++)
 | 
							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
 | 
					// Almost the same as d3d9 and gl3 function
 | 
				
			||||||
@ -1691,23 +1691,22 @@ rasterFromImage(Raster *raster, Image *image)
 | 
				
			|||||||
	int tw;
 | 
						int tw;
 | 
				
			||||||
	transferMinSize(image->depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
 | 
						transferMinSize(image->depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
 | 
				
			||||||
	tw = max(image->width, minw);
 | 
						tw = max(image->width, minw);
 | 
				
			||||||
	in = image->pixels;
 | 
						uint8 *src = image->pixels;
 | 
				
			||||||
	out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
 | 
						out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
 | 
				
			||||||
	if(image->depth == 4){
 | 
						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){
 | 
						}else if(image->depth == 8){
 | 
				
			||||||
		copyPSMT8(out, in, image->width, image->height, tw);
 | 
							copyPSMT8(out, tw, src, image->stride, image->width, image->height);
 | 
				
			||||||
	}else{
 | 
						}else{
 | 
				
			||||||
		// TODO: stride
 | 
							for(int32 y = 0; y < image->height; y++){
 | 
				
			||||||
		for(int32 y = 0; y < image->height; y++)
 | 
								in = src;
 | 
				
			||||||
			for(int32 x = 0; x < image->width; x++)
 | 
								for(int32 x = 0; x < image->width; x++){
 | 
				
			||||||
				switch(raster->format & 0xF00){
 | 
									switch(raster->format & 0xF00){
 | 
				
			||||||
				case Raster::C8888:
 | 
									case Raster::C8888:
 | 
				
			||||||
					out[0] = in[0];
 | 
										out[0] = in[0];
 | 
				
			||||||
					out[1] = in[1];
 | 
										out[1] = in[1];
 | 
				
			||||||
					out[2] = in[2];
 | 
										out[2] = in[2];
 | 
				
			||||||
					out[3] = in[3]*128/255;
 | 
										out[3] = in[3]*128/255;
 | 
				
			||||||
					in += 4;
 | 
					 | 
				
			||||||
					out += 4;
 | 
										out += 4;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case Raster::C888:
 | 
									case Raster::C888:
 | 
				
			||||||
@ -1715,19 +1714,20 @@ rasterFromImage(Raster *raster, Image *image)
 | 
				
			|||||||
					out[1] = in[1];
 | 
										out[1] = in[1];
 | 
				
			||||||
					out[2] = in[2];
 | 
										out[2] = in[2];
 | 
				
			||||||
					out[3] = 0x80;
 | 
										out[3] = 0x80;
 | 
				
			||||||
					in += 3;
 | 
					 | 
				
			||||||
					out += 4;
 | 
										out += 4;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case Raster::C1555:
 | 
									case Raster::C1555:
 | 
				
			||||||
					out[0] = in[0];
 | 
										conv_ARGB1555_from_ABGR1555(out, in);
 | 
				
			||||||
					out[1] = in[1];
 | 
					 | 
				
			||||||
					in += 2;
 | 
					 | 
				
			||||||
					out += 2;
 | 
										out += 2;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					assert(0 && "unknown ps2 raster format");
 | 
										assert(0 && "unknown ps2 raster format");
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									in += image->bpp;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								src += image->stride;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	raster->unlock(0);
 | 
						raster->unlock(0);
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
@ -1792,16 +1792,16 @@ rasterToImage(Raster *raster)
 | 
				
			|||||||
	int tw;
 | 
						int tw;
 | 
				
			||||||
	transferMinSize(depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
 | 
						transferMinSize(depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
 | 
				
			||||||
	tw = max(raster->width, minw);
 | 
						tw = max(raster->width, minw);
 | 
				
			||||||
	out = image->pixels;
 | 
						uint8 *dst = image->pixels;
 | 
				
			||||||
	in = raster->lock(0, Raster::LOCKREAD);
 | 
						in = raster->lock(0, Raster::LOCKREAD);
 | 
				
			||||||
	if(depth == 4){
 | 
						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){
 | 
						}else if(depth == 8){
 | 
				
			||||||
		copyPSMT8(out, in, raster->width, raster->height, tw);
 | 
							copyPSMT8(dst, image->stride, in, tw, raster->width, raster->height);
 | 
				
			||||||
	}else
 | 
						}else{
 | 
				
			||||||
		// TODO: stride
 | 
							for(int32 y = 0; y < image->height; y++){
 | 
				
			||||||
		for(int32 y = 0; y < image->height; y++)
 | 
								out = dst;
 | 
				
			||||||
			for(int32 x = 0; x < image->width; x++)
 | 
								for(int32 x = 0; x < image->width; x++){
 | 
				
			||||||
				switch(raster->format & 0xF00){
 | 
									switch(raster->format & 0xF00){
 | 
				
			||||||
				case Raster::C8888:
 | 
									case Raster::C8888:
 | 
				
			||||||
					out[0] = in[0];
 | 
										out[0] = in[0];
 | 
				
			||||||
@ -1809,31 +1809,31 @@ rasterToImage(Raster *raster)
 | 
				
			|||||||
					out[2] = in[2];
 | 
										out[2] = in[2];
 | 
				
			||||||
					out[3] = in[3]*255/128;
 | 
										out[3] = in[3]*255/128;
 | 
				
			||||||
					in += 4;
 | 
										in += 4;
 | 
				
			||||||
					out += 4;
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case Raster::C888:
 | 
									case Raster::C888:
 | 
				
			||||||
					out[0] = in[0];
 | 
										out[0] = in[0];
 | 
				
			||||||
					out[1] = in[1];
 | 
										out[1] = in[1];
 | 
				
			||||||
					out[2] = in[2];
 | 
										out[2] = in[2];
 | 
				
			||||||
					in += 4;
 | 
										in += 4;
 | 
				
			||||||
					out += 3;
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case Raster::C1555:
 | 
									case Raster::C1555:
 | 
				
			||||||
					out[0] = in[0];
 | 
										conv_ARGB1555_from_ABGR1555(out, in);
 | 
				
			||||||
					out[1] = in[1];
 | 
					 | 
				
			||||||
					in += 2;
 | 
										in += 2;
 | 
				
			||||||
					out += 2;
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case Raster::C555:
 | 
									case Raster::C555:
 | 
				
			||||||
					out[0] = in[0];
 | 
										conv_ARGB1555_from_ABGR1555(out, in);
 | 
				
			||||||
					out[1] = in[1] | 0x80;
 | 
										out[1] |= 0x80;
 | 
				
			||||||
					in += 2;
 | 
										in += 2;
 | 
				
			||||||
					out += 2;
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					assert(0 && "unknown ps2 raster format");
 | 
										assert(0 && "unknown ps2 raster format");
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									out += image->bpp;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								dst += image->stride;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	raster->unlock(0);
 | 
						raster->unlock(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return image;
 | 
						return image;
 | 
				
			||||||
 | 
				
			|||||||
@ -223,8 +223,9 @@ Texture *readNativeTexture(Stream *stream);
 | 
				
			|||||||
void writeNativeTexture(Texture *tex, Stream *stream);
 | 
					void writeNativeTexture(Texture *tex, Stream *stream);
 | 
				
			||||||
uint32 getSizeNativeTexture(Texture *tex);
 | 
					uint32 getSizeNativeTexture(Texture *tex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void expandPSMT4(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 copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw);
 | 
					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
 | 
					void
 | 
				
			||||||
conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in)
 | 
					conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	out[0] = in[0];
 | 
						out[0] = in[0];
 | 
				
			||||||
	out[1] = in[1];
 | 
						out[1] = in[1];
 | 
				
			||||||
@ -231,7 +231,7 @@ conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in)
 | 
					conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	out[0] = in[0];
 | 
						out[0] = in[0];
 | 
				
			||||||
	out[1] = in[1];
 | 
						out[1] = in[1];
 | 
				
			||||||
@ -240,7 +240,7 @@ conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
conv_RGB888_to_RGB888(uint8 *out, uint8 *in)
 | 
					conv_RGB888_from_RGB888(uint8 *out, uint8 *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	out[0] = in[0];
 | 
						out[0] = in[0];
 | 
				
			||||||
	out[1] = in[1];
 | 
						out[1] = in[1];
 | 
				
			||||||
@ -248,7 +248,7 @@ conv_RGB888_to_RGB888(uint8 *out, uint8 *in)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in)
 | 
					conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32 r, g, b, a;
 | 
						uint32 r, g, b, a;
 | 
				
			||||||
	a = (in[1]>>7) & 1;
 | 
						a = (in[1]>>7) & 1;
 | 
				
			||||||
@ -260,7 +260,7 @@ conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in)
 | 
					conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32 r, g, b, a;
 | 
						uint32 r, g, b, a;
 | 
				
			||||||
	a = (in[1]>>7) & 1;
 | 
						a = (in[1]>>7) & 1;
 | 
				
			||||||
@ -273,4 +273,14 @@ conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in)
 | 
				
			|||||||
	out[3] = a*0xFF;
 | 
						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 setPixelsDXT(int32 type, uint8 *pixels);
 | 
				
			||||||
	void setPalette(uint8 *palette);
 | 
						void setPalette(uint8 *palette);
 | 
				
			||||||
	bool32 hasAlpha(void);
 | 
						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);
 | 
						void removeMask(void);
 | 
				
			||||||
	Image *extractMask(void);
 | 
						Image *extractMask(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -150,6 +154,7 @@ struct Image
 | 
				
			|||||||
	static void printSearchPath(void);
 | 
						static void printSearchPath(void);
 | 
				
			||||||
	static char *getFilename(const char*);
 | 
						static char *getFilename(const char*);
 | 
				
			||||||
	static Image *read(const char *imageName);
 | 
						static Image *read(const char *imageName);
 | 
				
			||||||
 | 
						static Image *readMasked(const char *imageName, const char *maskName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	typedef Image *(*fileRead)(const char *afilename);
 | 
						typedef Image *(*fileRead)(const char *afilename);
 | 
				
			||||||
@ -166,6 +171,38 @@ void writeTGA(Image *image, const char *filename);
 | 
				
			|||||||
Image *readBMP(const char *filename);
 | 
					Image *readBMP(const char *filename);
 | 
				
			||||||
void writeBMP(Image *image, 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
 | 
					// used to emulate d3d and xbox textures
 | 
				
			||||||
struct RasterLevels
 | 
					struct RasterLevels
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -265,11 +302,13 @@ struct Raster
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in);
 | 
					void conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in);
 | 
				
			||||||
void conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in);
 | 
					void conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in);
 | 
				
			||||||
void conv_RGB888_to_RGB888(uint8 *out, uint8 *in);
 | 
					void conv_RGB888_from_RGB888(uint8 *out, uint8 *in);
 | 
				
			||||||
void conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in);
 | 
					void conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in);
 | 
				
			||||||
void conv_RGBA1555_to_RGBA8888(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
 | 
					#define IGNORERASTERIMP 0
 | 
				
			||||||
 | 
				
			|||||||
@ -299,14 +299,13 @@ defaultFindCB(const char *name)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: actually read the mask!
 | 
					 | 
				
			||||||
static Texture*
 | 
					static Texture*
 | 
				
			||||||
defaultReadCB(const char *name, const char *mask)
 | 
					defaultReadCB(const char *name, const char *mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Texture *tex;
 | 
						Texture *tex;
 | 
				
			||||||
	Image *img;
 | 
						Image *img;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	img = Image::read(name);
 | 
						img = Image::readMasked(name, mask);
 | 
				
			||||||
	if(img){
 | 
						if(img){
 | 
				
			||||||
		tex = Texture::create(Raster::createFromImage(img));
 | 
							tex = Texture::create(Raster::createFromImage(img));
 | 
				
			||||||
		strncpy(tex->name, name, 32);
 | 
							strncpy(tex->name, name, 32);
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,9 @@ void genIm3DEnd(void);
 | 
				
			|||||||
void initFont(void);
 | 
					void initFont(void);
 | 
				
			||||||
void printScreen(const char *s, float x, float y);
 | 
					void printScreen(const char *s, float x, float y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void initsplines(void);
 | 
				
			||||||
 | 
					void rendersplines(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rw::Charset *testfont;
 | 
					rw::Charset *testfont;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#include <Windows.h>
 | 
					//#include <Windows.h>
 | 
				
			||||||
@ -236,7 +239,7 @@ InitRW(void)
 | 
				
			|||||||
	Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
 | 
						Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
 | 
				
			||||||
	camera->m_rwcam = Scene.camera;
 | 
						camera->m_rwcam = Scene.camera;
 | 
				
			||||||
	camera->m_aspectRatio = 640.0f/448.0f;
 | 
						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 = 450.0f;
 | 
				
			||||||
	camera->m_far = 15.0f;
 | 
						camera->m_far = 15.0f;
 | 
				
			||||||
	camera->m_target.set(0.0f, 0.0f, 0.0f);
 | 
						camera->m_target.set(0.0f, 0.0f, 0.0f);
 | 
				
			||||||
@ -248,6 +251,8 @@ InitRW(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	Scene.world->addCamera(camera->m_rwcam);
 | 
						Scene.world->addCamera(camera->m_rwcam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initsplines();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -382,7 +387,7 @@ Draw(float timeDelta)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	getFrontBuffer();
 | 
						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->m_rwcam->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
 | 
				
			||||||
	camera->update();
 | 
						camera->update();
 | 
				
			||||||
	camera->m_rwcam->beginUpdate();
 | 
						camera->m_rwcam->beginUpdate();
 | 
				
			||||||
@ -401,10 +406,12 @@ extern void endSoftras(void);
 | 
				
			|||||||
	//	im2dtest();
 | 
						//	im2dtest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	Scene.clump->render();
 | 
					//	Scene.clump->render();
 | 
				
			||||||
	im3dtest();
 | 
					//	im3dtest();
 | 
				
			||||||
//	printScreen("Hello, World!", 10, 10);
 | 
					//	printScreen("Hello, World!", 10, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testfont->print("foo ABC", 200, 200, true);
 | 
					//	testfont->print("foo ABC", 200, 200, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rendersplines();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	camera->m_rwcam->endUpdate();
 | 
						camera->m_rwcam->endUpdate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user