-Added ability to use cubic interpolation on image resize (little more quality on non-po2 resizing)

-Added ability for exporter to shrink images to non-integer values. Helps if you want to convert your game artwork from 1080->720 or similar
This commit is contained in:
Juan Linietsky 2015-10-01 16:25:36 -03:00
parent 0840303a9c
commit e055247b17
8 changed files with 501 additions and 393 deletions

View File

@ -400,6 +400,102 @@ Image::Format Image::get_format() const{
return format;
}
static double _bicubic_interp_kernel( double x ) {
x = ABS(x);
double bc = 0;
if ( x <= 1 )
bc = ( 1.5 * x - 2.5 ) * x * x + 1;
else if ( x < 2 )
bc = ( ( -0.5 * x + 2.5 ) * x - 4 ) * x + 2;
return bc;
}
template<int CC>
static void _scale_cubic(const uint8_t* p_src, uint8_t* p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
// get source image size
int width = p_src_width;
int height = p_src_height;
double xfac = (double) width / p_dst_width;
double yfac = (double) height / p_dst_height;
// coordinates of source points and cooefficiens
double ox, oy, dx, dy, k1, k2;
int ox1, oy1, ox2, oy2;
// destination pixel values
// width and height decreased by 1
int ymax = height - 1;
int xmax = width - 1;
// temporary pointer
for ( int y = 0; y < p_dst_height; y++ ) {
// Y coordinates
oy = (double) y * yfac - 0.5f;
oy1 = (int) oy;
dy = oy - (double) oy1;
for ( int x = 0; x < p_dst_width; x++ ) {
// X coordinates
ox = (double) x * xfac - 0.5f;
ox1 = (int) ox;
dx = ox - (double) ox1;
// initial pixel value
uint8_t *dst=p_dst + (y*p_dst_width+x)*CC;
double color[CC];
for(int i=0;i<CC;i++) {
color[i]=0;
}
for ( int n = -1; n < 3; n++ ) {
// get Y cooefficient
k1 = _bicubic_interp_kernel( dy - (double) n );
oy2 = oy1 + n;
if ( oy2 < 0 )
oy2 = 0;
if ( oy2 > ymax )
oy2 = ymax;
for ( int m = -1; m < 3; m++ ) {
// get X cooefficient
k2 = k1 * _bicubic_interp_kernel( (double) m - dx );
ox2 = ox1 + m;
if ( ox2 < 0 )
ox2 = 0;
if ( ox2 > xmax )
ox2 = xmax;
// get pixel of original image
const uint8_t *p = p_src + (oy2 * p_src_width + ox2)*CC;
for(int i=0;i<CC;i++) {
color[i]+=p[i]*k2;
}
}
}
for(int i=0;i<CC;i++) {
dst[i]=CLAMP(Math::fast_ftoi(color[i]),0,255);
}
}
}
}
template<int CC>
static void _scale_bilinear(const uint8_t* p_src, uint8_t* p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
@ -559,6 +655,17 @@ void Image::resize( int p_width, int p_height, Interpolation p_interpolation ) {
}
} break;
case INTERPOLATE_CUBIC: {
switch(get_format_pixel_size(format)) {
case 1: _scale_cubic<1>(r_ptr,w_ptr,width,height,p_width,p_height); break;
case 2: _scale_cubic<2>(r_ptr,w_ptr,width,height,p_width,p_height); break;
case 3: _scale_cubic<3>(r_ptr,w_ptr,width,height,p_width,p_height); break;
case 4: _scale_cubic<4>(r_ptr,w_ptr,width,height,p_width,p_height); break;
}
} break;
}

View File

@ -91,6 +91,7 @@ public:
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
/* INTERPOLATE GAUSS */
};

View File

@ -1420,12 +1420,12 @@ EditorImportExport::ImageAction EditorImportExport::get_export_image_action() co
return image_action;
}
void EditorImportExport::set_export_image_shrink(int p_shrink) {
void EditorImportExport::set_export_image_shrink(float p_shrink) {
image_shrink=p_shrink;
}
int EditorImportExport::get_export_image_shrink() const{
float EditorImportExport::get_export_image_shrink() const{
return image_shrink;
}
@ -1496,12 +1496,12 @@ bool EditorImportExport::image_export_group_get_make_atlas(const StringName& p_e
return image_groups[p_export_group].make_atlas;
}
void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,int p_amount){
void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,float p_amount){
ERR_FAIL_COND(!image_groups.has(p_export_group));
image_groups[p_export_group].shrink=p_amount;
}
int EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{
float EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{
ERR_FAIL_COND_V(!image_groups.has(p_export_group),1);
return image_groups[p_export_group].shrink;

View File

@ -252,7 +252,7 @@ protected:
ImageAction action;
bool make_atlas;
float lossy_quality;
int shrink;
float shrink;
};
Vector<Ref<EditorExportPlugin> > export_plugins;
@ -260,7 +260,7 @@ protected:
Map<String,int> by_idx;
ImageAction image_action;
float image_action_compress_quality;
int image_shrink;
float image_shrink;
Set<String> image_formats;
ExportFilter export_filter;
@ -310,8 +310,8 @@ public:
void set_export_image_action(ImageAction p_action);
ImageAction get_export_image_action() const;
void set_export_image_shrink(int p_shrink);
int get_export_image_shrink() const;
void set_export_image_shrink(float p_shrink);
float get_export_image_shrink() const;
void set_export_image_quality(float p_quality);
float get_export_image_quality() const;
@ -326,8 +326,8 @@ public:
ImageAction image_export_group_get_image_action(const StringName& p_export_group) const;
void image_export_group_set_make_atlas(const StringName& p_export_group,bool p_make);
bool image_export_group_get_make_atlas(const StringName& p_export_group) const;
void image_export_group_set_shrink(const StringName& p_export_group,int p_amount);
int image_export_group_get_shrink(const StringName& p_export_group) const;
void image_export_group_set_shrink(const StringName& p_export_group,float p_amount);
float image_export_group_get_shrink(const StringName& p_export_group) const;
void image_export_group_set_lossy_quality(const StringName& p_export_group,float p_quality);
float image_export_group_get_lossy_quality(const StringName& p_export_group) const;

View File

@ -828,7 +828,7 @@ Error EditorTextureImportPlugin::import(const String& p_path, const Ref<Resource
}
Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink) {
Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink) {
if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
@ -866,7 +866,7 @@ Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &textur
int orig_w=image.get_width();
int orig_h=image.get_height();
image.resize(orig_w/shrink,orig_h/shrink);
image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
texture->create_from_image(image,tex_flags);
texture->set_size_override(Size2(orig_w,orig_h));
@ -926,7 +926,7 @@ Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &textur
int orig_h=image.get_height();
if (shrink>1) {
image.resize(orig_w/shrink,orig_h/shrink);
image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
texture->create_from_image(image,tex_flags);
texture->set_size_override(Size2(orig_w,orig_h));
}
@ -987,7 +987,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
print_line("path: "+p_path+" flags: "+itos(tex_flags));
int shrink=1;
float shrink=1;
if (from->has_option("shrink"))
shrink=from->get_option("shrink");

View File

@ -70,7 +70,7 @@ private:
static EditorTextureImportPlugin *singleton[MODE_MAX];
//used by other importers such as mesh
Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink);
Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink);
void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller);
public:

View File

@ -1156,7 +1156,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
image_shrink = memnew( SpinBox );
image_shrink->set_min(1);
image_shrink->set_max(8);
image_shrink->set_step(1);
image_shrink->set_step(0.1);
image_vb->add_margin_child("Shrink All Images:",image_shrink);
sections->add_child(image_vb);
@ -1237,7 +1237,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
group_shrink->set_min(1);
group_shrink->set_max(8);
group_shrink->set_val(1);
group_shrink->set_step(1);
group_shrink->set_step(0.001);
group_options->add_margin_child("Shrink By:",group_shrink);
group_shrink->connect("value_changed",this,"_group_changed");