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); } } }