Exemplo n.º 1
0
// Reads Tiff Images
RGBAImage* RGBAImage::ReadTiff(char *filename)
{
	RGBAImage *fimg = 0;
	
    TIFF* tif = TIFFOpen(filename, "r");
    char emsg[1024];
    if (tif) {
		TIFFRGBAImage img;
		
		if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
			size_t npixels;
			uint32* raster;

			npixels = img.width * img.height;
			raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
			if (raster != NULL) {
				if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) {
					// result is in ABGR
					fimg = new RGBAImage(img.width, img.height);
					for (int y = 0; y < img.height; y++) {
						for (int x = 0; x < img.width; x++) {
						   fimg->Set(x,y, raster[x + y * img.width]);
						}
					}
				}
			_TIFFfree(raster);
			}
	    }
	    TIFFRGBAImageEnd(&img);
	} else {
	    TIFFError(filename, emsg);
	}
	return fimg;
}
Exemplo n.º 2
0
	static RGBAImage *ReadFromFile(const string &filename)
	{
		cout << "reading from file:" << filename << "\n";
		vector<uint8_t> lodepng_image; //the raw pixels
		unsigned width, height;
		unsigned error = lodepng::decode(lodepng_image, width, height, filename.c_str());
		if (error) {
			cout << "decoder error " << error << ": " << lodepng_error_text(error) << endl;
			return NULL;
		}

		//the pixels are now in the vector "image", 4 bytes per pixel, 
		//ordered RGBARGBA..., use it as texture, draw it, ...
		cout << "width " << width << ", height " << height << "\n";

		RGBAImage *rgbaimg = new RGBAImage(width,height,filename);

		for(unsigned y = 0; y < height; y += 1) {
		for(unsigned x = 0; x < width; x += 1) {
			uint32_t red = lodepng_image[4 * y * width + 4 * x + 0]; //red
			uint32_t green = lodepng_image[4 * y * width + 4 * x + 1]; //green
			uint32_t blue = lodepng_image[4 * y * width + 4 * x + 2]; //blue
			uint32_t alpha = lodepng_image[4 * y * width + 4 * x + 3]; //alpha
			rgbaimg->Set( red, green, blue, alpha, y*width+x );
		}
		}

		return rgbaimg;
	}
Exemplo n.º 3
0
Image* LoadHLWBuff( byte* buffer ){
	byte *buf_p;
	unsigned long mipdatasize;
	int columns, rows, numPixels;
	byte *pixbuf;
	int row, column;
	byte *palette;
	LPWAD3_MIP lpMip;
	unsigned char red, green, blue, alphabyte;

	lpMip = (LPWAD3_MIP)buffer; //!\todo Make endian-safe.

	mipdatasize = GET_MIP_DATA_SIZE( lpMip->width,lpMip->height );

	palette = buffer + mipdatasize + 2;

	buf_p = buffer + lpMip->offsets[0];

	columns = lpMip->width;
	rows = lpMip->height;
	numPixels = columns * rows;

	RGBAImage* image = new RGBAImage( columns, rows );

	for ( row = 0; row < rows; row++ )
	{
		pixbuf = image->getRGBAPixels() + row * columns * 4;

		for ( column = 0; column < columns; column++ )
		{
			int palIndex;

			palIndex = *buf_p++;

			red = *( palette + ( palIndex * 3 ) );
			green = *( palette + ( palIndex * 3 ) + 1 );
			blue = *( palette + ( palIndex * 3 ) + 2 );

			// HalfLife engine makes pixels that are BLUE transparent.
			// So show them that way in the editor.
			if ( blue == 0xff && red == 0x00 && green == 0x00 ) {
				alphabyte = 0x00;
				blue = 0x00; // don't set the resulting pixel to blue
			}
			else
			{
				alphabyte = 0xff;
			}

			*pixbuf++ = red;
			*pixbuf++ = green;
			*pixbuf++ = blue;

			*pixbuf++ = alphabyte;
		}
	}

	return image;
}
Exemplo n.º 4
0
/**
 * Simple octree color quantization: Similar to http://rosettacode.org/wiki/Color_quantization#C
 */
void octreeColorQuantize(const RGBAImage& image, size_t max_colors,
		std::vector<RGBAPixel>& colors, Octree** octree) {
	assert(max_colors > 0);

	// have an octree with the colors as leaves
	Octree* internal_octree = new Octree();
	// and a priority queue of leaves to be processed
	// the order of leaves is very important, see NodeComparator
	std::priority_queue<Octree*, std::vector<Octree*>, NodeComparator> queue;

	// insert the colors into the octree
	for (int x = 0; x < image.getWidth(); x++) {
		for (int y = 0; y < image.getHeight(); y++) {
			RGBAPixel color = image.pixel(x, y);
			Octree* node = Octree::findOrCreateNode(internal_octree, color);
			node->setColor(color);
			// add the leaf only once to the queue
			if (node->getCount() == 1)
				queue.push(node);
		}
	}

	// now: reduce the leaves until we have less colors than maximum
	while (queue.size() > max_colors) {
		Octree* node = queue.top();
		assert(node->isLeaf());
		queue.pop();
		
		// add the color value of the leaf to the parent
		node->reduceToParent();
		Octree* parent = node->getParent();
		// delete the leaf (leaf is automatically removed from parent in reduceToParent())
		delete node;

		// add parent to queue if it is a leaf now
		if (parent->isLeaf())
			queue.push(parent);
	}

	// gather the quantized colors
	while (queue.size()) {
		Octree* node = queue.top();
		assert(node->isLeaf());
		node->setColorID(colors.size());
		colors.push_back(node->getColor());
		queue.pop();
	}

	if (octree != nullptr)
		*octree = internal_octree;
	else
		delete internal_octree;
}
Exemplo n.º 5
0
GLuint GLUtils::generateTexture(const RGBAImage &img, GLuint &tex)
{
    int width = img.width();
    int height = img.height();
    cout<<"Image size: "<<width<<"x"<<height<<endl;
    cout<<"Generating image texture..."<<endl;
    GLfloat *m = new GLfloat[width * height * 4];

    int i, j;
    //float c;

    for (i = 0; i < height; i++) {
        int y = i;
        for (j = 0; j < width; j++) {
            int x = j;
            float r = img(x, y, 0);
            float g = img(x, y, 1);
            float b = img(x, y, 2);
            float a = img(x, y, 3);
            int baseIdx = (y * width + x) * 4;
            //float randVaue = (float)rand()/(float)RAND_MAX;
            m[baseIdx+ 0] = r;
            m[baseIdx+ 1] = g;
            m[baseIdx+ 2] = b;
            m[baseIdx+ 3] = a;
        }
    }

    glEnable(GL_TEXTURE_2D);
    glDeleteTextures(1, &tex);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
                    GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                    GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, width,
                 height, 0, GL_RGBA, GL_FLOAT,
                 m);
    glDisable(GL_TEXTURE_2D);

    cout<<"Image texture ID: "<<tex<<endl;

    delete[] m;

    return tex;
}
Exemplo n.º 6
0
static Image* LoadImage (ArchiveFile& file, const char *extension)
{
	RGBAImage* image = (RGBAImage *) 0;

	/* load the buffer from pk3 or filesystem */
	ScopedArchiveBuffer buffer(file);

	GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_type(extension, (GError**) 0);
	if (loader == (GdkPixbufLoader*)0) {
		g_warning("could not get a loader for: '%s'\n", extension);
		return image;
	}

	GError *error = (GError *) 0;
	if (gdk_pixbuf_loader_write(loader, (const guchar *) buffer.buffer, static_cast<gsize> (buffer.length),
			&error)) {
		int pos = 0;
		GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
		const int width = gdk_pixbuf_get_width(pixbuf);
		const int height = gdk_pixbuf_get_height(pixbuf);
		const gboolean hasAlpha = gdk_pixbuf_get_has_alpha(pixbuf);
		const int stepWidth = gdk_pixbuf_get_n_channels(pixbuf);
		const guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);

		image = new RGBAImage(width, height, false);
		byte *rgba = image->getRGBAPixels();
		const int rowextra = gdk_pixbuf_get_rowstride(pixbuf) - width * stepWidth;

		for (int y = 0; y < height; ++y, pixels += rowextra) {
			for (int x = 0; x < width; ++x) {
				rgba[pos++] = *(pixels++);
				rgba[pos++] = *(pixels++);
				rgba[pos++] = *(pixels++);
				if (hasAlpha && *pixels != 255)
					image->setHasAlpha(true);
				rgba[pos++] = hasAlpha ? *(pixels++) : 255;
			}
		}

		g_object_unref(pixbuf);
	} else {
		g_warning("image could not get loaded: '%s' %s\n",
				file.getName().c_str(), (error != (GError *) 0) ? error->message : "");
		if (error)
			g_error_free(error);
	}

	gdk_pixbuf_loader_close(loader, (GError**) 0);

	return image;
}
Exemplo n.º 7
0
static Image* LoadImageGDK (ArchiveFile& file)
{
	// Allocate a new GdkPixBuf and create an alpha-channel with alpha=1.0
	GdkPixbuf* rawPixbuf = gdk_pixbuf_new_from_file(file.getName().c_str(), NULL);

	// Only create an alpha channel if the other rawPixbuf could be loaded
	GdkPixbuf* img = (rawPixbuf != NULL) ? gdk_pixbuf_add_alpha(rawPixbuf, TRUE, 255, 0, 255) : NULL;

	if (img != NULL) {
		// Allocate a new image
		RGBAImage* image = new RGBAImage(gdk_pixbuf_get_width(img), gdk_pixbuf_get_height(img), false);

		// Initialise the source buffer pointers
		guchar* gdkStart = gdk_pixbuf_get_pixels(img);
		int rowstride = gdk_pixbuf_get_rowstride(img);
		int numChannels = gdk_pixbuf_get_n_channels(img);

		// Set the target buffer pointer to the first RGBAPixel
		RGBAPixel* targetPixel = image->pixels;

		// Now do an unelegant cycle over all the pixels and move them into the target
		for (unsigned int y = 0; y < image->height; y++) {
			for (unsigned int x = 0; x < image->width; x++) {
				guchar* gdkPixel = gdkStart + y * rowstride + x * numChannels;

				// Copy the values from the GdkPixel
				targetPixel->red = gdkPixel[0];
				targetPixel->green = gdkPixel[1];
				targetPixel->blue = gdkPixel[2];
				targetPixel->alpha = gdkPixel[3];
				if (targetPixel->alpha != 255)
					image->setHasAlpha(true);

				// Increase the pointer
				targetPixel++;
			}
		}

		// Free the GdkPixbufs from the memory
		g_object_unref(G_OBJECT(img));
		g_object_unref(G_OBJECT(rawPixbuf));

		return image;
	} else {
		g_warning("image could not get loaded: '%s'\n", file.getName().c_str());
	}

	// No image could be loaded, return NULL
	return NULL;
}
Exemplo n.º 8
0
Image* LoadDDSBuff( const byte* buffer ){
	int width, height;
	ddsPF_t pixelFormat;
	if ( DDSGetInfo( reinterpret_cast<ddsBuffer_t*>( const_cast<byte*>( buffer ) ), &width, &height, &pixelFormat ) == -1 ) {
		return 0;
	}

	RGBAImage* image = new RGBAImage( width, height );

	if ( DDSDecompress( reinterpret_cast<ddsBuffer_t*>( const_cast<byte*>( buffer ) ), image->getRGBAPixels() ) == -1 ) {
		image->release();
		return 0;
	}
	return image;
}
Exemplo n.º 9
0
static RGBAImage *ToRGBAImage(FIBITMAP *image, const char *filename=NULL)
{
	const int w = FreeImage_GetWidth(image);
	const int h = FreeImage_GetHeight(image);

	RGBAImage* result = new RGBAImage(w, h, filename);
	// Copy the image over to our internal format, FreeImage has the scanlines bottom to top though.
	unsigned int* dest = result->Get_Data();
	for( int y=0; y < h; y++, dest += w )
	{
		const unsigned int* scanline = reinterpret_cast<const unsigned int*>(FreeImage_GetScanLine(image, h - y - 1));
		memcpy(dest, scanline, sizeof(dest[0]) * w);
	}

	return result;
}
Exemplo n.º 10
0
void testPNG()
{
	RGBAImage img;
	img.create(100, 100);
	for (vector<RGBAPixel>::iterator it = img.data.begin(); it != img.data.end(); it++)
	{
		*it = ((rand() % 256) << 24) | ((rand() % 256) << 16) | ((rand() % 256) << 8) | (rand() % 256);
	}
	img.writePNG("test.png");

	RGBAImage img2;
	img2.readPNG("test.png");
	if (img2.data != img.data)
		cout << "images don't match after trip through PNG!" << endl;
	else
		cout << "PNG test successful" << endl;
}
Exemplo n.º 11
0
Image* LoadMDLImageBuff( byte* buffer ){
	if ( !LoadPalette() ) {
		return 0;
	}

	if ( !ident_equal( buffer, MDL_IDENT ) ) {
		globalErrorStream() << "LoadMDLImage: data has wrong ident\n";
		return 0;
	}

	PointerInputStream inputStream( buffer );
	inputStream.seek( 4 + 4 + 12 + 12 + 4 + 12 );
	//int numskins =
	istream_read_int32_le( inputStream );
	int skinwidth = istream_read_int32_le( inputStream );
	int skinheight = istream_read_int32_le( inputStream );
	inputStream.seek( 4 + 4 + 4 + 4 + 4 + 4 );

	switch ( istream_read_int32_le( inputStream ) )
	{
	case MDL_SKIN_SINGLE:
		break;
	case MDL_SKIN_GROUP:
		int numskins = istream_read_int32_le( inputStream );
		inputStream.seek( numskins * 4 );
		break;
	}

	RGBAImage* image = new RGBAImage( skinwidth, skinheight );
	unsigned char* pRGBA = image->getRGBAPixels();

	for ( int i = 0; i < ( skinheight ); i++ )
	{
		for ( int j = 0; j < ( skinwidth ); j++ )
		{
			byte index = istream_read_byte( inputStream );
			*pRGBA++ = mdl_palette[index * 3 + 0];
			*pRGBA++ = mdl_palette[index * 3 + 1];
			*pRGBA++ = mdl_palette[index * 3 + 2];
			*pRGBA++ = 255;
		}
	}

	return image;
}
Exemplo n.º 12
0
static Image* LoadJPGBuff_( const void *src_buffer, int src_size ){
	struct jpeg_decompress_struct cinfo;
	struct my_jpeg_error_mgr jerr;

	cinfo.err = jpeg_std_error( &jerr.pub );
	jerr.pub.error_exit = my_jpeg_error_exit;

	if ( setjmp( jerr.setjmp_buffer ) ) { //< TODO: use c++ exceptions instead of setjmp/longjmp to handle errors
		globalErrorStream() << "WARNING: JPEG library error: " << errormsg << "\n";
		jpeg_destroy_decompress( &cinfo );
		return 0;
	}

	jpeg_create_decompress( &cinfo );
	jpeg_buffer_src( &cinfo, const_cast<void*>( src_buffer ), src_size );
	jpeg_read_header( &cinfo, TRUE );
	jpeg_start_decompress( &cinfo );

	int row_stride = cinfo.output_width * cinfo.output_components;

	RGBAImage* image = new RGBAImage( cinfo.output_width, cinfo.output_height );

	JSAMPARRAY buffer = ( *cinfo.mem->alloc_sarray )( ( j_common_ptr ) & cinfo, JPOOL_IMAGE, row_stride, 1 );

	while ( cinfo.output_scanline < cinfo.output_height )
	{
		jpeg_read_scanlines( &cinfo, buffer, 1 );

		if ( cinfo.out_color_components == 4 ) {
			j_putRGBAScanline( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 );
		}
		else if ( cinfo.out_color_components == 3 ) {
			j_putRGBScanline( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 );
		}
		else if ( cinfo.out_color_components == 1 ) {
			j_putGrayScanlineToRGB( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 );
		}
	}

	jpeg_finish_decompress( &cinfo );
	jpeg_destroy_decompress( &cinfo );

	return image;
}
Exemplo n.º 13
0
void CaveRendermode::draw(RGBAImage& image, const mc::BlockPos& pos,
		uint16_t id, uint16_t data) {
	// a nice color gradient to see something
	// (because the whole map is just full of cave stuff,
	// one can't differentiate the single caves)

	double h1 = (double) (64 - pos.y) / 64;
	if (pos.y > 64)
		h1 = 0;

	double h2 = 0;
	if (pos.y >= 64 && pos.y < 96)
		h2 = (double) (96 - pos.y) / 32;
	else if (pos.y > 16 && pos.y < 64)
		h2 = (double) (pos.y - 16) / 48;

	double h3 = 0;
	if (pos.y > 64)
		h3 = (double) (pos.y - 64) / 64;
	
	int R = h1 * 128.0 + 128.0;
	int G = h2 * 255.0;
	int B = h3 * 255.0;
	
	int Y = (R*3+G*10+B)/14; //get luminance of recolor
	
	// We try to do luminance-neutral additive/subtractive color instead of alpha blending, for better contrast
	// So first subtract luminance from each component.
	R = (R-Y)/3; // /3 is similar to alpha=85
	G = (G-Y)/3;
	B = (B-Y)/3;
	
	int size = image.getWidth();
	for (int y = 0; y < size; y++)
		for (int x = 0; x < size; x++) {
			uint32_t pixel = image.getPixel(x, y);
			if (pixel != 0) {				
				image.setPixel(x,y, rgba_add_clamp(pixel, R, G, B));
			}
		}
}
Exemplo n.º 14
0
void TopdownTileRenderer::renderTile(const TilePos& tile_pos, RGBAImage& tile) {
	int texture_size = images->getTextureSize();
	tile.setSize(getTileSize(), getTileSize());

	for (int x = 0; x < tile_width; x++) {
		for (int z = 0; z < tile_width; z++) {
			mc::ChunkPos chunkpos(tile_pos.getX() * tile_width + x, tile_pos.getY() * tile_width + z);
			current_chunk = world->getChunk(chunkpos);
			if (current_chunk != nullptr)
				renderChunk(*current_chunk, tile, texture_size*16*x, texture_size*16*z);
		}
	}
}
Exemplo n.º 15
0
void testOctreeWithImage(const RGBAImage& image) {
	std::set<RGBAPixel> colors;
	int r = 0, g = 0, b = 0, count = 0;

	Octree octree;

	// insert all pixels into an octree
	for (int x = 0; x < image.getWidth(); x++) {
		for (int y = 0; y < image.getHeight(); y++) {
			RGBAPixel color = image.getPixel(x, y);
			colors.insert(color);
			r += rgba_red(color);
			g += rgba_green(color);
			b += rgba_blue(color);
			count++;

			Octree::findOrCreateNode(&octree, color)->setColor(color);
		}
	}

	// make sure that all colors are inserted correctly
	BOOST_CHECK(octree.isRoot() && !octree.isLeaf());
	BOOST_CHECK(!octree.hasColor());

	// reduce all colors up to the root of the tree
	// the color should be the overall average color
	traverseReduceOctree(&octree);
	BOOST_CHECK(octree.hasColor());

	RGBAPixel average1 = octree.getColor();
	RGBAPixel average2 = rgba(r / count, g / count, b / count, 255);
	BOOST_CHECK_EQUAL(average1, average2);

	BOOST_TEST_MESSAGE("Overall colors: " << colors.size());
	BOOST_TEST_MESSAGE("Pixels per color: " << (double) (image.getWidth() * image.getHeight()) / colors.size());
	BOOST_TEST_MESSAGE("Average color: " << (int) rgba_red(average1) << ","
			<< (int) rgba_green(average1) << "," << (int) rgba_blue(average1));
}
Exemplo n.º 16
0
static std::shared_ptr<FIBITMAP> to_free_image(const RGBAImage &image)
{
    const auto *data = image.get_data();

    std::shared_ptr<FIBITMAP> bitmap(
        FreeImage_Allocate(image.get_width(), image.get_height(), 32,
                           0x000000ff, 0x0000ff00, 0x00ff0000),
        FreeImageDeleter());
    assert(bitmap.get());

    for (auto y = 0u; y < image.get_height();
         y++, data += image.get_width())
    {
        auto scanline = reinterpret_cast<unsigned int *>(
            FreeImage_GetScanLine(bitmap.get(), image.get_height() - y - 1));
        memcpy(scanline, data, sizeof(data[0]) * image.get_width());
    }

    return bitmap;
}
Exemplo n.º 17
0
void TopdownTileRenderer::renderChunk(const mc::Chunk& chunk, RGBAImage& tile, int dx, int dy) {
	// TODO implement preblit water render behavior

	int texture_size = images->getTextureSize();

	for (int x = 0; x < 16; x++) {
		for (int z = 0; z < 16; z++) {
			std::deque<RenderBlock> blocks;

			// TODO make this water thing a bit nicer
			bool in_water = false;
			int water = 0;

			mc::LocalBlockPos localpos(x, z, 0);
			//int height = chunk.getHeightAt(localpos);
			//localpos.y = height;
			localpos.y = -1;
			if (localpos.y >= mc::CHUNK_HEIGHT*16 || localpos.y < 0)
				localpos.y = mc::CHUNK_HEIGHT*16 - 1;

			uint16_t id = chunk.getBlockID(localpos);
			while (id == 0 && localpos.y > 0) {
				localpos.y--;
				id = chunk.getBlockID(localpos);
			}
			if (localpos.y < 0)
				continue;

			while (localpos.y >= 0) {
				mc::BlockPos globalpos = localpos.toGlobalPos(chunk.getPos());

				id = chunk.getBlockID(localpos);
				if (id == 0) {
					in_water = false;
					localpos.y--;
					continue;
				}
				uint16_t data = chunk.getBlockData(localpos);
				bool is_water = (id == 8 || id == 9) && data == 0;

				if (render_mode->isHidden(globalpos, id, data)) {
					localpos.y--;
					continue;
				}

				if (is_water && !use_preblit_water) {
					if (is_water == in_water) {
						localpos.y--;
						continue;
					}
					in_water = is_water;
				} else if (use_preblit_water) {
					if (!is_water)
						water = 0;
					else {
						water++;
						if (water > images->getMaxWaterPreblit()) {
							auto it = blocks.begin();
							while (it != blocks.end()) {
								auto current = it++;
								if (it == blocks.end() || (it->id != 8 && it->id != 9)) {
									RenderBlock& top = *current;
									// blocks.erase(current);

									top.id = 8;
									top.data = OPAQUE_WATER;
									top.block = images->getBlock(top.id, top.data);
									render_mode->draw(top.block, top.pos, top.id, top.data);
									// blocks.insert(current, top);
									break;
								} else {
									blocks.erase(current);
								}
							}
							break;
						}
					}
				}

				data = checkNeighbors(globalpos, id, data);
				
				RGBAImage block = images->getBlock(id, data);
				if (Biome::isBiomeBlock(id, data)) {
					block = images->getBiomeBlock(id, data, getBiomeOfBlock(globalpos, &chunk));
				}

				render_mode->draw(block, globalpos, id, data);
				RenderBlock render_block;
				render_block.block = block;
				render_block.id = id;
				render_block.data = data;
				render_block.pos = globalpos;
				blocks.push_back(render_block);

				if (!images->isBlockTransparent(id, data))
					break;
				localpos.y--;
			}

			while (blocks.size() > 0) {
				RenderBlock render_block = blocks.back();
				tile.alphaBlit(render_block.block, dx + x*texture_size, dy + z*texture_size);
				blocks.pop_back();
			}
		}
	}
}
Exemplo n.º 18
0
bool expandMap(const string& outputpath)
{
	// read old params
	MapParams mp;
	if (!mp.readFile(outputpath))
	{
		cerr << "pigmap.params missing or corrupt" << endl;
		return false;
	}
	int32_t tileSize = mp.tileSize();

	// to expand a map, the following must be done:
	//  1. the top-left quadrant of the current zoom level 1 needs to be moved to zoom level 2, where
	//     it will become the bottom-right quadrant of the top-left quadrant of the new zoom level 1,
	//     so the top-level file "0.png" and subdirectory "0" must become "0/3.png" and "0/3",
	//     respectively; and similarly for the other three quadrants
	//  2. new zoom level 1 tiles must be created: "0.png" is 3/4 empty, but has a shrunk version of
	//     the old "0.png" (which is the new "0/3.png") in its bottom-right, etc.
	//  3. a new "base.png" must be created from the new zoom level 1 tiles

	// move everything at zoom 1 or higher one level deeper
	// ...first the subdirectories
	renameFile(outputpath + "/0", outputpath + "/old0");
	renameFile(outputpath + "/1", outputpath + "/old1");
	renameFile(outputpath + "/2", outputpath + "/old2");
	renameFile(outputpath + "/3", outputpath + "/old3");
	makePath(outputpath + "/0");
	makePath(outputpath + "/1");
	makePath(outputpath + "/2");
	makePath(outputpath + "/3");
	renameFile(outputpath + "/old0", outputpath + "/0/3");
	renameFile(outputpath + "/old1", outputpath + "/1/2");
	renameFile(outputpath + "/old2", outputpath + "/2/1");
	renameFile(outputpath + "/old3", outputpath + "/3/0");
	// ...now the zoom 1 files
	const char* formatExtensions[] = {".png", ".jpeg"};
	ImageSettings::Format formats[] = {ImageSettings::Format_PNG, ImageSettings::Format_JPEG};
	for (int i = 0; i < 2; ++i) {
		if (ImageSettings::format == formats[i] || ImageSettings::format == ImageSettings::Format_Both)
		{
			const char* format = formatExtensions[i];
			renameFile(outputpath + "/0" + format, outputpath + "/0/3" + format);
			renameFile(outputpath + "/1" + format, outputpath + "/1/2" + format);
			renameFile(outputpath + "/2" + format, outputpath + "/2/1" + format);
			renameFile(outputpath + "/3" + format, outputpath + "/3/0" + format);
		}
	}

	// build the new zoom 1 tiles
	RGBAImage old0img;
	bool used0 = old0img.readPNG(outputpath + "/0/3.png");
	RGBAImage new0img;
	new0img.create(tileSize, tileSize);
	if (used0)
	{
		reduceHalf(new0img, ImageRect(tileSize/2, tileSize/2, tileSize/2, tileSize/2), old0img);
		new0img.writeImage(outputpath + "/0");
	}
	RGBAImage old1img;
	bool used1 = old1img.readPNG(outputpath + "/1/2.png");
	RGBAImage new1img;
	new1img.create(tileSize, tileSize);
	if (used1)
	{
		reduceHalf(new1img, ImageRect(0, tileSize/2, tileSize/2, tileSize/2), old1img);
		new1img.writeImage(outputpath + "/1");
	}
	RGBAImage old2img;
	bool used2 = old2img.readPNG(outputpath + "/2/1.png");
	RGBAImage new2img;
	new2img.create(tileSize, tileSize);
	if (used2)
	{
		reduceHalf(new2img, ImageRect(tileSize/2, 0, tileSize/2, tileSize/2), old2img);
		new2img.writeImage(outputpath + "/2");
	}
	RGBAImage old3img;
	bool used3 = old3img.readPNG(outputpath + "/3/0.png");
	RGBAImage new3img;
	new3img.create(tileSize, tileSize);
	if (used3)
	{
		reduceHalf(new3img, ImageRect(0, 0, tileSize/2, tileSize/2), old3img);
		new3img.writeImage(outputpath + "/3");
	}

	// build the new base tile
	RGBAImage newbase;
	newbase.create(tileSize, tileSize);
	if (used0)
		reduceHalf(newbase, ImageRect(0, 0, tileSize/2, tileSize/2), new0img);
	if (used1)
		reduceHalf(newbase, ImageRect(tileSize/2, 0, tileSize/2, tileSize/2), new1img);
	if (used2)
		reduceHalf(newbase, ImageRect(0, tileSize/2, tileSize/2, tileSize/2), new2img);
	if (used3)
		reduceHalf(newbase, ImageRect(tileSize/2, tileSize/2, tileSize/2, tileSize/2), new3img);
	newbase.writeImage(outputpath + "/base");

	// write new params (with incremented baseZoom)
	mp.baseZoom++;
	mp.writeFile(outputpath);

	// touch all tiles, to prevent browser cache mishaps (since many new tiles will have the same
	//  filename as some old tile, but possibly with an earlier timestamp)
	if (system((string("find ") + outputpath + " -exec touch {} +").c_str()) < 0)
        cerr << "Error changing mtimes. Ignoring..." << endl;

	return true;
}
Exemplo n.º 19
0
Image* LoadIDSPBuff( byte *buffer ){
	byte *buf_p;
	int columns, rows;
	byte *pixbuf;

	int row, column;
	byte *palette;
	unsigned char red, green, blue, alphabyte;

	dspriteheader_t *header;
	dspritev1_t         *pinv1;
	dspritev2_t         *pinv2;
	dspriteframetype_t  *pframetype;
	int version;
	int numframes;
	dspriteframe_t *spriteframe;

	header = (dspriteheader_t *)buffer;

	if ( header->ident != IDSPRITEHEADER ) {
		globalWarningStream() << "WARNING: IDSP file has wrong header\n";
		return 0;
	}

	version = header->version;
	if ( version != 1 && version != 2 ) {
		globalWarningStream() << "WARNING: IDSP file has wrong version number "
							   "(" << version << " should be 1 or 2)\n";
		return 0;
	}

	// initialise variables depending on the sprite version.
	switch ( version )
	{
	case 1:
		pinv1 = (dspritev1_t *)( header + 1 );
		numframes = pinv1->numframes;
		columns = pinv1->width;
		rows = pinv1->height;
		pframetype = (dspriteframetype_t *)( pinv1 + 1 );
		break;
	case 2:
		pinv2 = (dspritev2_t *)( header + 1 );
		numframes = pinv2->numframes;
		columns = pinv2->width;
		rows = pinv2->height;
		pframetype = (dspriteframetype_t *)( pinv2 + 1 );
		break;
	default:
		globalWarningStream() << "WARNING: IDSP file has unsupported version\n";
		return 0;
	}
	if ( numframes > 1 ) {
		globalWarningStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n";
	}

	// palette = buffer+mipdatasize+2;
	// buf_p = buffer+lpMip->offsets[0];

	RGBAImage* image = new RGBAImage( columns, rows );

#ifdef DEBUG
	frametype = spriteframetype_t( pframetype->type );
	if ( frametype == SPR_SINGLE ) {
		globalOutputStream() << "Single Frame\n";
	}
	else if ( frametype == SPR_GROUP ) {
		globalOutputStream() << "Group of Frames\n";
	}
	else
	{
		globalWarningStream() << "Bleh!\n"; // <-- we always get this, wtf!
	}
#endif

	palette = (byte *)( pframetype + 1 );
	spriteframe = (dspriteframe_t *)( palette + ( 256 * 3 ) + 4 ); // what are those 4 extra bytes ? what's missing ?
	buf_p = (byte *)( spriteframe + 1 );

	for ( row = 0; row < rows; row++ )
	{
		pixbuf = image->getRGBAPixels() + row * columns * 4;

		for ( column = 0; column < columns; column++ )
		{
			int palIndex;

			palIndex = *buf_p++;

			red = *( palette + ( palIndex * 3 ) );
			green = *( palette + ( palIndex * 3 ) + 1 );
			blue = *( palette + ( palIndex * 3 ) + 2 );

			// HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF)
			// So show them that way in the editor.
			if ( blue == 0xff && red == 0x00 && green == 0x00 ) {
				alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly)
				blue = 0x00; // don't set the resulting pixel to blue
			}
			else
			{
				alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly)
			}

			*pixbuf++ = red;
			*pixbuf++ = green;
			*pixbuf++ = blue;

			*pixbuf++ = alphabyte;
		}
	}

	return image;
}
Exemplo n.º 20
0
void IsometricTileRenderer::renderTile(const TilePos& tile_pos, RGBAImage& tile) {
	// some vars, set correct image size
	int block_size = images->getBlockSize();
	tile.setSize(getTileSize(), getTileSize());

	// get the maximum count of water blocks
	// blitted about each over, until they are nearly opaque
	int max_water = images->getMaxWaterPreblit();

	// all visible blocks which are rendered in this tile
	std::set<RenderBlock> blocks;

	// iterate over the highest blocks in the tile
	// we use as tile position tile_pos+tile_offset because the offset means that
	// we treat the tile position as tile_pos, but it's actually tile_pos+tile_offset
	for (TileTopBlockIterator it(tile_pos, block_size, tile_width);
			!it.end(); it.next()) {
		// water render behavior n1:
		// are we already in a row of water?
		bool in_water = false;

		// water render behavior n2:
		// water counter, how many water blocks are at the moment in this row?
		int water = 0;

		// the render block objects in our current block row
		std::set<RenderBlock> row_nodes;
		// then iterate over the blocks, which are on the tile at the same position,
		// beginning from the highest block
		for (BlockRowIterator block(it.current); !block.end(); block.next()) {
			// get current chunk position
			mc::ChunkPos current_chunk_pos(block.current);

			// check if current chunk is not null
			// and if the chunk wasn't replaced in the cache (i.e. position changed)
			if (current_chunk == nullptr || current_chunk->getPos() != current_chunk_pos)
				// get chunk if not
				//if (!state.world->hasChunkSection(current_chunk, block.current.y))
				//	continue;
				current_chunk = world->getChunk(current_chunk_pos);
			if (current_chunk == nullptr) {
				// here is nothing (= air),
				// so reset state if we are in water
				in_water = false;
				continue;
			}

			// get local block position
			mc::LocalBlockPos local(block.current);

			// now get block id
			uint16_t id = current_chunk->getBlockID(local);
			// air is completely transparent so continue
			if (id == 0) {
				in_water = false;
				continue;
			}

			// now get the block data
			uint16_t data = current_chunk->getBlockData(local);

			// check if the render mode hides this block
			if (render_mode->isHidden(block.current, id, data))
				continue;

			bool is_water = (id == 8 || id == 9) && data == 0;
			if (is_water && !use_preblit_water) {
				// water render behavior n1:
				// render only the top sides of the water blocks
				// and darken the ground with the lighting data
				// used for lighting rendermode

				// if we are already in water, skip checking this water block
				if (is_water && in_water)
					continue;
				in_water = is_water;

			} else if (use_preblit_water) {
				// water render behavior n2:
				// render the top side of every water block
				// have also preblit water blocks to skip redundant alphablitting

				// no lighting is needed because the 'opaque-water-effect'
				// is created by blitting the top sides of the water blocks
				// one above the other

				if (!is_water) {
					// if not water, reset the counter
					water = 0;
				} else {
					water++;

					// when we have enough water in a row
					// we can stop searching more blocks
					// and replace the already added render blocks with a preblit water block
					if (water > max_water) {
						std::set<RenderBlock>::const_iterator it = row_nodes.begin();
						// iterate through the render blocks in this row
						while (it != row_nodes.end()) {
							std::set<RenderBlock>::const_iterator current = it++;
							// check if we have reached the top most water block
							if (it == row_nodes.end() || (it->id != 8 && it->id != 9)) {
								RenderBlock top = *current;
								row_nodes.erase(current);

								// check for neighbors
								mc::Block south, west;
								south = getBlock(top.pos + mc::DIR_SOUTH);
								west = getBlock(top.pos + mc::DIR_WEST);

								id = 8;
								data = OPAQUE_WATER;
								bool neighbor_south = !south.isFullWater();
								if (neighbor_south)
								//	data |= DATA_SOUTH;
									data |= OPAQUE_WATER_SOUTH;
								bool neighbor_west = !west.isFullWater();
								if (neighbor_west)
								//	data |= DATA_WEST;
									data |= OPAQUE_WATER_WEST;

								// get image and replace the old render block with this
								//top.image = images->getOpaqueWater(neighbor_south,
								//		neighbor_west);
								top.image = images->getBlock(id, data);

								// don't forget the render mode
								render_mode->draw(top.image, top.pos, id, data);

								row_nodes.insert(top);
								break;

							} else {
								// water render block
								row_nodes.erase(current);
							}
						}

						break;
					}
				}
			}

			// check for special data (neighbor related)
			// get block image, check for transparency, create render block...
			data = checkNeighbors(block.current, id, data);
			//if (is_water && (data & DATA_WEST) && (data & DATA_SOUTH))
			//	continue;
			RGBAImage image;
			bool transparent = images->isBlockTransparent(id, data);

			// check for biome data
			if (Biome::isBiomeBlock(id, data))
				image = images->getBiomeBlock(id, data, getBiomeOfBlock(block.current, current_chunk));
			else
				image = images->getBlock(id, data);

			RenderBlock node;
			node.x = it.draw_x;
			node.y = it.draw_y;
			node.pos = block.current;
			node.image = image;
			node.id = id;
			node.data = data;

			// let the render mode do their magic with the block image
			render_mode->draw(node.image, node.pos, id, data);

			// insert into current row
			row_nodes.insert(node);

			// if this block is not transparent, then break
			if (!transparent)
				break;
		}

		// iterate through the created render blocks
		for (std::set<RenderBlock>::const_iterator it = row_nodes.begin();
		        it != row_nodes.end(); ++it) {
			std::set<RenderBlock>::const_iterator next = it;
			next++;
			// insert render block to
			if (next == row_nodes.end()) {
				blocks.insert(*it);
			} else {
				// skip unnecessary leaves
				if (it->id == 18 && next->id == 18 && (next->data & 3) == (it->data & 3))
					continue;
				blocks.insert(*it);
			}
		}
	}

	// now blit all blocks
	for (std::set<RenderBlock>::const_iterator it = blocks.begin(); it != blocks.end();
			++it) {
		tile.alphaBlit(it->image, it->x, it->y);
	}
}