Ejemplo n.º 1
0
void PLTFile::getColorRows(byte rows[4 * 256 * kLayerMAX], const uint8 colors[kLayerMAX]) {
	for (uint i = 0; i < kLayerMAX; i++, rows += 4 * 256) {
		ImageDecoder *palette = 0;

		try {
			palette = getLayerPalette(i, colors[i]);

			// The images have their origin at the bottom left, so we flip the color row
			const uint8 row = palette->getMipMap(0).height - 1 - colors[i];

			// Copy the whole row into the buffer
			memcpy(rows, palette->getMipMap(0).data + (row * 4 * 256), 4 * 256);

		} catch (Common::Exception &e) {
			// On error set to pink (while honoring intensity), for high debug visibility
			for (uint32 p = 0; p < 256; p++) {
				rows[p * 4 + 0] = p;
				rows[p * 4 + 1] = 0x00;
				rows[p * 4 + 2] = p;
				rows[p * 4 + 3] = 0xFF;
			}

			e.add("Failed to load palette \"%s\"", kPalettes[i]);
			Common::printException(e, "WARNING: ");
		}

		delete palette;
	}
}
Ejemplo n.º 2
0
/** Load a specific layer palette image and perform some sanity checks. */
ImageDecoder *PLTFile::getLayerPalette(uint32 layer, uint8 row) {
	assert(layer < kLayerMAX);

	// TODO: We may want to cache these somehow...
	ImageDecoder *palette = loadImage(kPalettes[layer]);
	try {
		if (palette->getFormat() != kPixelFormatBGRA)
			throw Common::Exception("Invalid format (%d)", palette->getFormat());

		if (palette->getMipMapCount() < 1)
			throw Common::Exception("No mip maps");

		const ImageDecoder::MipMap &mipMap = palette->getMipMap(0);

		if (mipMap.width != 256)
			throw Common::Exception("Invalid width (%d)", mipMap.width);

		if (row >= mipMap.height)
			throw Common::Exception("Invalid height (%d >= %d)", row, mipMap.height);

	} catch (...) {
		delete palette;
		throw;
	}

	return palette;
}
Ejemplo n.º 3
0
void Cursor::load() {
	::Aurora::FileType type;

	Common::SeekableReadStream *img = ResMan.getResource(::Aurora::kResourceCursor, _name, &type);
	if (!img)
		throw Common::Exception("No such cursor resource \"%s\"", _name.c_str());

	_hotspotX = 0;
	_hotspotY = 0;

	ImageDecoder *image;
	// Loading the different image formats
	if      (type == ::Aurora::kFileTypeTGA)
		image = new TGA(*img);
	else if (type == ::Aurora::kFileTypeDDS)
		image = new DDS(*img);
	else if (type == ::Aurora::kFileTypeCUR) {
		WinIconImage *cursor = new WinIconImage(*img);

		if (_hotspotX < 0)
			_hotspotX = cursor->getHotspotX();
		if (_hotspotY < 0)
			_hotspotY = cursor->getHotspotY();

		image = cursor;
	} else {
		delete img;
		throw Common::Exception("Unsupported cursor resource type %d", (int) type);
	}

	delete img;

	_width  = image->getMipMap(0).width;
	_height = image->getMipMap(0).height;

	TXI txi;
	txi.getFeatures().filter = false;

	try {
		Texture *texture = new Texture(image, &txi);

		image = 0;

		try {
			_texture = TextureMan.add(texture, _name);
		} catch(...) {
			delete texture;
			throw;
		}

	} catch (...) {
		delete image;
		throw;
	}

	_hotspotX = CLIP(_hotspotX, 0, _width  - 1);
	_hotspotY = CLIP(_hotspotY, 0, _height - 1);
}
Ejemplo n.º 4
0
/* Create a tinted texture by combining the tint map with the tint colors.
 *
 * This is currently all done here in software and has several drawbacks:
 * - Slow
 * - We're creating lots of uncompressed RBGA texture, so it
 *   takes up a lot of memory, both on the GPU and in system RAM
 *
 * TODO: We really need to do this in shaders in the future.
 */
void ModelNode_NWN2::createTint() {
	if (_tintMap.empty())
		return;

	ImageDecoder *tintMap   = 0;
	Surface      *tintedMap = 0;
	try {
		// Load and uncompress the texture
		tintMap = Texture::loadImage(_tintMap);
		if (tintMap->isCompressed())
			tintMap->decompress();

		const ImageDecoder::MipMap &tintImg = tintMap->getMipMap(0);

		// Create a new target surface with the same dimensions
		tintedMap = new Surface(tintImg.width, tintImg.height);
		ImageDecoder::MipMap &tintedImg = tintedMap->getMipMap();

		// Iterate over all pixels: read values, mix tints, write pixel to target surface
		for (int n = 0; n < tintImg.width * tintImg.height; n++) {
			float srcColor[4], dstColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
			tintImg.getPixel(n, srcColor[0], srcColor[1], srcColor[2], srcColor[3]);

			if (srcColor[3] != 0.0f) {
				// Mix using the value and the alpha components as intensities
				// TODO: Verify how the mixing is actually done in NWN2!
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++)
						dstColor[j] += _tint[i][j] * srcColor[i] * _tint[i][3] * srcColor[3] * _diffuse[i];
				}
			} else
				// Source alpha is 0.0f: No tinting for this pixel
				for (int i = 0; i < 3; i++)
					dstColor[i] = _diffuse[i] * _tint[i][3];

			tintedImg.setPixel(n, dstColor[0], dstColor[1], dstColor[2], dstColor[3]);
		}

	} catch (...) {
		delete tintMap;
		delete tintedMap;
		return;
	}

	delete tintMap;

	// And add the new texture to the TextureManager
	TextureHandle tintedTexture = TextureMan.add(Texture::create(tintedMap));

	_textures.push_back(tintedTexture);
	_tintedMapIndex = _textures.size() - 1;
}