Example #1
0
// Save current image in file [true = success, false otherwise]
bool PNG::save(string pathname) const{
	//create encoder and set settings and info (optional)
	LodePNG::Encoder encoder;
	encoder.getSettings().zlibsettings.windowSize = 2048;

	//encode and save
	std::vector<unsigned char> buffer;
	encoder.encode(buffer, image.empty() ? 0 : &image[0], width, height);
	LodePNG::saveFile(buffer, pathname);
	
	if(encoder.hasError())
	{
		return false;
	}
	return true;
}
Example #2
0
bool ImageWriter::convert( Image* image )
{
    #pragma TODO("Fix the LodePNG image writing code to the new API")

#if defined(ENABLE_IMAGE_WRITER_)
	LodePNG::Encoder encoder;
	
	LodePNG_InfoColor& png = encoder.getInfoPng().color;
	LodePNG_InfoColor& raw = encoder.getInfoRaw().color;
	
	switch(image->getPixelFormat())
	{
	case PixelFormat::Depth:
		png.colorType = 0;
		raw.colorType = 0;
		break;
	case PixelFormat::R8G8B8:
		png.colorType = 2;
		raw.colorType = 2;
		break;
	case PixelFormat::R8G8B8A8:
		png.colorType = 6;
		raw.colorType = 6;
		break;
	default:
		LogError("Pixel format is not supported");
		return false;
	}

	raw.bitDepth = 8;
	
	encoder.encode(output, image->getBuffer(),
		image->getWidth(), image->getHeight());

	if( encoder.hasError() )
	{
		LogError("Could not encode image to PNG");
		return false;
	}

	return true;
#else
	return false;
#endif
}
Example #3
0
bool ProceduralTexture::savePNG(char *png_map)
{
	std::vector<unsigned char> buffer;
		
	//create encoder and set settings and info (optional)
	LodePNG::Encoder encoder;
	encoder.addText("Comment", "CubicVR Procedural Texture");
	encoder.getSettings().zlibsettings.windowSize = 2048;
	
	encoder.encode(buffer, image.empty() ? 0 : &image[0], width, height);
	
	if(encoder.hasError())
	{
		Logger::log(LOG_ERROR,"[savePng] Error %d\n", encoder.getError());
		return false;
	}
	
	LodePNG::saveFile(buffer, png_map);
	
	return true;
}
Example #4
0
int LuaCube::saveScreenshot(lua_State *L)
{    
    const char *filename = luaL_checkstring(L, 1);
    Cube::LCD &lcd = LuaSystem::sys->cubes[id].lcd;
    std::vector<uint8_t> pixels;
    
    for (unsigned i = 0; i < lcd.FB_SIZE; i++) {
        RGB565 color = lcd.fb_mem[i];
        pixels.push_back(color.red());
        pixels.push_back(color.green());
        pixels.push_back(color.blue());
        pixels.push_back(0xFF);
    }

    LodePNG::Encoder encoder;
    std::vector<uint8_t> pngData;
    encoder.encode(pngData, pixels, lcd.WIDTH, lcd.HEIGHT);
    
    LodePNG::saveFile(pngData, filename);
    
    return 0;
}
Example #5
0
void FW::exportLodePngImage(OutputStream& stream, const Image* image)
{
    // Select format and convert.

    FW_ASSERT(image);
    const Vec2i& size = image->getSize();
    bool hasAlpha = image->getFormat().hasChannel(ImageFormat::ChannelType_A);
    ImageFormat::ID format = (hasAlpha) ? ImageFormat::R8_G8_B8_A8 : ImageFormat::R8_G8_B8;

    Image* converted = NULL;
    if (image->getFormat().getID() != format)
    {
        converted = new Image(size, format);
        *converted = *image;
    }

    // Encode image.

    LodePNG::Encoder encoder;
    int colorType = (hasAlpha) ? 6 : 2;
    encoder.getSettings().autoLeaveOutAlphaChannel = false;
    encoder.getInfoRaw().color.colorType = colorType;
    encoder.getInfoPng().color.colorType = colorType;

    std::vector<U8> dataBuffer;
    encoder.encode(dataBuffer, (U8*)((converted) ? converted : image)->getPtr(), size.x, size.y);

    if (encoder.hasError())
        setError("exportLodePngImage(): LodePNG error %d!", encoder.getError());

    // Write to the output stream.

    if (!hasError() && !dataBuffer.empty())
        stream.write(&dataBuffer[0], (int)dataBuffer.size());

    // Clean up.

    delete converted;
}
Example #6
0
int save_png_SDFont(
		const char* orig_filename,
		const char* font_name,
		int img_width, int img_height,
		const std::vector< unsigned char > &img_data,
		std::vector< sdf_glyph > &packed_glyphs,
		const std::map<int, int> & char_map,
		int font_size )
{
	//	save my image
	int fn_size = strlen( orig_filename ) + 100;
	char *fn = new char[ fn_size ];
	sprintf( fn, "%s_sdf.png", orig_filename );
	printf( "'%s'\n", fn );
	LodePNG::Encoder encoder;
	encoder.addText("Comment", "Signed Distance Font: lonesock tools");
	encoder.getSettings().zlibsettings.windowSize = 512; //	faster, not much worse compression
	std::vector<unsigned char> buffer;
	int tin = clock();
	encoder.encode( buffer, img_data.empty() ? 0 : &img_data[0], img_width, img_height );
	LodePNG::saveFile( buffer, fn );
	tin = clock() - tin;
	
	// remap from unicode to codepage, get font height
	float ymax = 0, ymin = 0;
	if( char_map.size() != 0 )
	{
		for( unsigned int i = 0; i < packed_glyphs.size(); ++i )
		{
			std::map<int, int>::const_iterator id;
			if( (id = char_map.find(packed_glyphs[i].ID)) != char_map.end() )
			{
				packed_glyphs[i].ID = id->second;
				float ymaxi = packed_glyphs[i].yoff;
				float ymini = packed_glyphs[i].yoff - packed_glyphs[i].height;
				if (ymax < ymaxi) ymax = ymaxi;
				if (ymin > ymini) ymin = ymini;
			}
		}
	}

	//	now save the acompanying info
	sprintf( fn, "%s_sdf.txt", orig_filename );
	FILE *fp = fopen( fn, "w" );
	if( fp )
	{
		fprintf( fp, "info face=\"%s\"\n", font_name  );
		fprintf( fp, "size=%i\n", font_size );
		fprintf( fp, "ascent=%2.0f\n", ymax );
		fprintf( fp, "descent=%2.0f\n", ymin );
		fprintf( fp, "chars count=%zu\n", packed_glyphs.size() );
		for( unsigned int i = 0; i < packed_glyphs.size(); ++i )
		{		
			fprintf( fp, "char id=%-6ix=%-6iy=%-6iwidth=%-6iheight=%-6i",
				packed_glyphs[i].ID,
				packed_glyphs[i].x,
				packed_glyphs[i].y,
				packed_glyphs[i].width,
				packed_glyphs[i].height );
			
			fprintf( fp, "xoffset=%-10.3fyoffset=%-10.3fxadvance=%-10.3f",
				packed_glyphs[i].xoff,
				packed_glyphs[i].yoff,
				packed_glyphs[i].xadv );
			
			fprintf( fp, "  page=0  chnl=0\n" );
		}
		fclose( fp );
	}
	delete [] fn;
	return tin;
}
Example #7
0
bool render_signed_distance_image(
		const char* image_file,
		int texture_size,
		bool export_c_header )
{
	//	try to load this file as an image
	int w, h, channels;
	unsigned char *img = stbi_load( image_file, &w, &h, &channels, 0 );
	if( !img )
	{
		return false;
	}
	//	image loaded
	printf( "Loaded '%s', %i x %i, channels 0", image_file, w, h );
	for( int i = 1; i < channels; ++i )
	{
		printf( ",%i", i );
	}
	printf( "\n" );
	//	check for components and resizing issues
	if( (w <= texture_size) && (h <= texture_size) )
	{
		printf( "The output texture size is larger than the input image dimensions!\n" );
		stbi_image_free( img );
		return false;
	}
	//	now, which channel do I use as the input function?
	int chan = 0;
	if( channels > 1 )
	{
		printf( "Which channel contains the input? " );
		scanf( "%i", &chan );
		if( chan < 0 )
		{
			chan = 0;
		} else if( chan >= channels )
		{
			chan = channels - 1;
		}
	}
	printf( "Using channel %i as the input\n", chan );
	std::vector<unsigned char> img_data;
	img_data.reserve( w*h );
	for( int i = chan; i < w*h*channels; i += channels )
	{
		img_data.push_back( img[i] );
	}
	stbi_image_free( img );
	//	is this channel strictly 2 values?
	bool needs_threshold = false;
	int vmax, vmin;
	{
		int val0 = img_data[0], val = -1;
		vmin = img_data[0];
		vmax = img_data[0];
		for( int i = 0; i < w*h; ++i )
		{
			//	do I need a threshold?
			if( img_data[i] != val0 )
			{
				if( val < 0 )
				{
					//	second value
					val = img_data[i];
				} else
				{
					needs_threshold = (val != img_data[i]);
				}
			}
			//	find min and max, just in case
			if( img_data[i] < vmin )
			{
				vmin = img_data[i];
			}
			if( img_data[i] > vmax )
			{
				vmax = img_data[i];
			}
		}
	}
	if( needs_threshold )
	{
		int thresh;
		printf( "The image needs a threshold, between %i and %i (< threshold is 0): ", vmin, vmax );
		scanf( "%i", &thresh );
		if( thresh <= vmin )
		{
			thresh = vmin + 1;
		} else if( thresh > vmax )
		{
			thresh = vmax;
		}
		printf( "using threshold=%i\n", thresh );
		for( int i = 0; i < w*h; ++i )
		{
			if( img_data[i] < thresh )
			{
				img_data[i] = 0;
			} else
			{
				img_data[i] = 255;
			}
		}
	}

	//	OK, I'm finally ready to perform the SDF analysis
	int sw;
	if( w > h )
	{
		sw = 2 * w / texture_size;
	} else
	{
		sw = 2 * h / texture_size;
	}
	std::vector<unsigned char> pdata( 4 * texture_size * texture_size, 0 );
	img = &(img_data[0]);
	for( int j = 0; j < texture_size; ++j )
	{
		for( int i = 0; i < texture_size; ++i )
		{
			int sx = i * (w-1) / (texture_size-1);
			int sy = j * (h-1) / (texture_size-1);
			int pd_idx = (i+j*texture_size) * 4;
			pdata[pd_idx] =
				get_SDF_radial
						( img, w, h,
						sx, sy, sw );
			pdata[pd_idx+1] = pdata[pd_idx];
			pdata[pd_idx+2] = pdata[pd_idx];
			pdata[pd_idx+3] = pdata[pd_idx];
		}
	}

	//	save the image
	int fn_size = strlen( image_file ) + 100;
	char *fn = new char[ fn_size ];
	#if 0
	sprintf( fn, "%s_sdf.bmp", image_file );
	stbi_write_bmp( fn, texture_size, texture_size, 4, &pdata[0] );
	#endif
	sprintf( fn, "%s_sdf.png", image_file );
	printf( "'%s'\n", fn );
	LodePNG::Encoder encoder;
	encoder.addText("Comment", "Signed Distance Image: lonesock tools");
	encoder.getSettings().zlibsettings.windowSize = 512; //	faster, not much worse compression
	std::vector<unsigned char> buffer;
	int tin = clock();
	encoder.encode( buffer, pdata.empty() ? 0 : &pdata[0], texture_size, texture_size );
	LodePNG::saveFile( buffer, fn );
	tin = clock() - tin;

	return true;
}