Ejemplo n.º 1
0
void CL_PNGProvider::save(CL_PixelBuffer buffer, CL_IODevice &iodev)
{
	if (buffer.get_format() != cl_abgr8)
	{
		CL_PixelBuffer newbuf(
			buffer.get_width(),
			buffer.get_height(), 
			cl_abgr8);
		buffer.convert(newbuf);
		buffer = newbuf;
	}

	png_structp png_ptr;
	png_infop info_ptr;

	png_ptr  = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info_ptr = png_create_info_struct(png_ptr);

	png_set_read_fn(png_ptr, &iodev, &CustomIOFunctions::read);
	png_set_write_fn(png_ptr, &iodev, &CustomIOFunctions::write, CustomIOFunctions::flush);

	#ifndef PNG_COLOR_TYPE_RGBA
	#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
	#endif

	png_set_IHDR(
		png_ptr, info_ptr, 
		buffer.get_width(), buffer.get_height(), 8 /* bitdepth */,
		PNG_COLOR_TYPE_RGBA,
		PNG_INTERLACE_NONE, 
		PNG_COMPRESSION_TYPE_BASE, 
		PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);

	png_uint_32 height = buffer.get_height();
	png_uint_32 row_bytes = buffer.get_width()*4;

	png_byte* image = new png_byte[height * row_bytes];
	png_bytep* row_pointers = new png_bytep[height];

	// fill the image with data
	for (int i = 0; i < buffer.get_width()*buffer.get_height()*4; ++i)
		image[i] = static_cast<unsigned char*>(buffer.get_data())[i];

	// generate row pointers
	for (unsigned int k = 0; k < height; k++)
		row_pointers[k] = image + (k * row_bytes);

	png_write_image(png_ptr, row_pointers);

	png_write_end(png_ptr, info_ptr);

	png_destroy_write_struct( &png_ptr, &info_ptr );

	delete[] image;
	delete[] row_pointers;
}
/** Returns a pointer to a new image, based on 'surface'
    but with changed hue. Changing the hue means to "rotate"
    the color spectrum. You can read more about the HSV color
    model on the Internet.
    This method is used to change the color of a sprite
    (e.g. a car or another object). I suggest to make the
    basic images in a red color-spectrum and create all
    other colors from it.
    For examples, please visit the Trophy homepage developer
    corner (http://trophy.sourceforge.net)
    \param hue Changing of hue: 0-360
    \param saturation Changing of saturation: -100...100
    \param value Changing of value (Color intensity): -100...100
*/
CL_PixelBuffer
CAImageManipulation::changeHSV( CL_PixelBuffer pixBufOriginal,
                                int hue, int saturation, int value )
{
    CL_PixelBuffer pixbuf(pixBufOriginal.get_width(), pixBufOriginal.get_height(), pixBufOriginal.get_format());
    pixBufOriginal.convert(pixbuf);

    CL_TextureFormat pf = pixbuf.get_format();
    // Check that we handle this pixel format
    if(pf != CL_TextureFormat::cl_rgba8 && pf != CL_TextureFormat::cl_rgb8 &&
            pf != CL_TextureFormat::cl_rgba4 )
    {
        std::cout << "Unknow pixel format !" << pf << std::endl;
        return pixBufOriginal.copy();
    }

    // Calc size in bytes:
    //
    int bpp = pixBufOriginal.get_bytes_per_pixel();
    int size = pixbuf.get_width() * pixbuf.get_height() * bpp;

    pixbuf.lock(CL_BufferAccess::cl_access_read_write);

    unsigned char *data = (unsigned char*)pixbuf.get_data();

    // Change hue:
    //
    int r, g, b, a(0);
    int h, s, v;

    for(int i=0; i<size; i+=bpp )
    {
        if(pf == CL_TextureFormat::cl_rgba8)
        {
            a = data[i];
            b = data[i+1];
            g = data[i+2];
            r = data[i+3];
        } else if (pf == CL_TextureFormat::cl_rgb8)
        {
            std::cout << "TextureFormat : rgb888\n";
            b = data[i];
            g = data[i+1];
            r = data[i+2];
        } else if (pf == CL_TextureFormat::cl_rgba4)
        {
            std::cout << "TextureFormat : rgba4444\n";
            r = data[i] && 0x0F;
            g = (data[i] && 0xF0) >> 4;
            b = data[i+1] && 0x0F;
            a = (data[i+1] && 0xF0) >> 4;
        }

        if( a!=0 && (r!=g || r!=b || g!=b) ) 
        {
            rgbToHsv( r, g, b, &h, &s, &v );

            h += hue;
            s += saturation;
            v += value;
            if( h > 360 ) h -= 360;
            if( s > 255 ) s = 255;
            if( v > 255 ) v = 255;
            if( h < 0 ) h += 360;
            if( s < 0 ) s = 0;
            if( v < 0 ) v = 0;

            hsvToRgb( h, s, v, &r, &g, &b );

            if(pf == CL_TextureFormat::cl_rgba8)
            {
                data[i] = a;
                data[i+1] = b;
                data[i+2] = g;
                data[i+3] = r;
            } else if (pf == CL_TextureFormat::cl_rgb8)
            {
                data[i] = b;
                data[i+1] = g;
                data[i+2] = r;
            } else if (pf == CL_TextureFormat::cl_rgba4)
            {
                data[i] = r + (g << 4);
                data[i+1] = b + (a << 4);
            }
        }
    }