diff options
Diffstat (limited to 'core/image.cpp')
-rw-r--r-- | core/image.cpp | 1213 |
1 files changed, 465 insertions, 748 deletions
diff --git a/core/image.cpp b/core/image.cpp index 3411a45aad..e949cd9b38 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -36,86 +36,186 @@ const char* Image::format_names[Image::FORMAT_MAX]={ - "Grayscale", - "Intensity", - "GrayscaleAlpha", - "RGB", - "RGBA", - "Indexed", - "IndexedAlpha", - "YUV422", - "YUV444", - "BC1", - "BC2", - "BC3", - "BC4", - "BC5", - "PVRTC2", - "PVRTC2Alpha", + "Lum8", //luminance + "LumAlpha8", //luminance-alpha + "Red8", + "RedGreen", + "RGB8", + "RGBA8", + "RGB565", //16 bit + "RGBA4444", + "RGBA5551", + "RFloat", //float + "RGFloat", + "RGBFloat", + "RGBAFloat", + "RHalf", //half float + "RGHalf", + "RGBHalf", + "RGBAHalf", + "DXT1", //s3tc + "DXT3", + "DXT5", + "ATI1", + "ATI2", + "BPTC_RGBA", + "BPTC_RGBF", + "BPTC_RGBFU", + "PVRTC2", //pvrtc + "PVRTC2A", "PVRTC4", - "PVRTC4Alpha", - "ETC", - "ATC", - "ATCAlphaExp", - "ATCAlphaInterp", + "PVRTC4A", + "ETC", //etc1 + "ETC2_R11", //etc2 + "ETC2_R11S", //signed", NOT srgb. + "ETC2_RG11", + "ETC2_RG11S", + "ETC2_RGB8", + "ETC2_RGBA8", + "ETC2_RGB8A1", }; SavePNGFunc Image::save_png_func = NULL; -void Image::_put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data) { - _put_pixelw(p_x,p_y,width,p_color,p_data); +void Image::_put_pixelb(int p_x,int p_y, uint32_t p_pixelsize,uint8_t *p_dst,const uint8_t *p_src) { + + uint32_t ofs=(p_y*width+p_x)*p_pixelsize; + + for(uint32_t i=0;i<p_pixelsize;i++) { + p_dst[ofs+i]=p_src[i]; + } } -void Image::_put_pixelw(int p_x,int p_y, int p_width, const BColor& p_color, unsigned char *p_data) { +void Image::_get_pixelb(int p_x,int p_y, uint32_t p_pixelsize,const uint8_t *p_src,uint8_t *p_dst) { + uint32_t ofs=(p_y*width+p_x)*p_pixelsize; - int ofs=p_y*p_width+p_x; + for(uint32_t i=0;i<p_pixelsize;i++) { + p_dst[ofs]=p_src[ofs+i]; + } - switch(format) { - case FORMAT_GRAYSCALE: { +} - p_data[ofs]=p_color.gray(); - } break; - case FORMAT_INTENSITY: { - p_data[ofs]=p_color.a; - } break; - case FORMAT_GRAYSCALE_ALPHA: { +int Image::get_format_pixel_size(Format p_format) { + + switch(p_format) { + case FORMAT_L8: return 1; //luminance + case FORMAT_LA8: return 2; //luminance-alpha + case FORMAT_R8: return 1; + case FORMAT_RG8: return 2; + case FORMAT_RGB8: return 3; + case FORMAT_RGBA8: return 4; + case FORMAT_RGB565: return 2; //16 bit + case FORMAT_RGBA4444: return 2; + case FORMAT_RGBA5551: return 2; + case FORMAT_RF: return 4; //float + case FORMAT_RGF: return 8; + case FORMAT_RGBF: return 12; + case FORMAT_RGBAF: return 16; + case FORMAT_RH: return 2; //half float + case FORMAT_RGH: return 4; + case FORMAT_RGBH: return 8; + case FORMAT_RGBAH: return 12; + case FORMAT_DXT1: return 1; //s3tc bc1 + case FORMAT_DXT3: return 1; //bc2 + case FORMAT_DXT5: return 1; //bc3 + case FORMAT_ATI1: return 1; //bc4 + case FORMAT_ATI2: return 1; //bc5 + case FORMAT_BPTC_RGBA: return 1; //btpc bc6h + case FORMAT_BPTC_RGBF: return 1; //float / + case FORMAT_BPTC_RGBFU: return 1; //unsigned float + case FORMAT_PVRTC2: return 1; //pvrtc + case FORMAT_PVRTC2A: return 1; + case FORMAT_PVRTC4: return 1; + case FORMAT_PVRTC4A: return 1; + case FORMAT_ETC: return 1; //etc1 + case FORMAT_ETC2_R11: return 1; //etc2 + case FORMAT_ETC2_R11S: return 1; //signed: return 1; NOT srgb. + case FORMAT_ETC2_RG11: return 1; + case FORMAT_ETC2_RG11S: return 1; + case FORMAT_ETC2_RGB8: return 1; + case FORMAT_ETC2_RGBA8: return 1; + case FORMAT_ETC2_RGB8A1: return 1; + case FORMAT_MAX: {} - p_data[ofs*2]=p_color.gray(); - p_data[ofs*2+1]=p_color.a; + } + return 0; +} + +void Image::get_format_min_pixel_size(Format p_format,int &r_w, int &r_h) { + + + switch(p_format) { + case FORMAT_DXT1: //s3tc bc1 + case FORMAT_DXT3: //bc2 + case FORMAT_DXT5: //bc3 + case FORMAT_ATI1: //bc4 + case FORMAT_ATI2: { //bc5 case case FORMAT_DXT1: + + r_w=4; + r_h=4; } break; - case FORMAT_RGB: { + case FORMAT_PVRTC2: + case FORMAT_PVRTC2A: { - p_data[ofs*3+0]=p_color.r; - p_data[ofs*3+1]=p_color.g; - p_data[ofs*3+2]=p_color.b; + r_w=16; + r_h=8; + } break; + case FORMAT_PVRTC4A: + case FORMAT_PVRTC4: { + r_w=8; + r_h=8; } break; - case FORMAT_RGBA: { + case FORMAT_ETC: { - p_data[ofs*4+0]=p_color.r; - p_data[ofs*4+1]=p_color.g; - p_data[ofs*4+2]=p_color.b; - p_data[ofs*4+3]=p_color.a; + r_w=4; + r_h=4; + } break; + case FORMAT_BPTC_RGBA: + case FORMAT_BPTC_RGBF: + case FORMAT_BPTC_RGBFU: { + r_w=4; + r_h=4; } break; - case FORMAT_INDEXED: - case FORMAT_INDEXED_ALPHA: { + case FORMAT_ETC2_R11: //etc2 + case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_RG11: + case FORMAT_ETC2_RG11S: + case FORMAT_ETC2_RGB8: + case FORMAT_ETC2_RGBA8: + case FORMAT_ETC2_RGB8A1: { + + r_w=4; + r_h=4; - ERR_FAIL(); } break; - default: {}; + default: { + r_w=1; + r_h=1; + } break; } } +int Image::get_format_pixel_rshift(Format p_format) { + + if (p_format==FORMAT_DXT1 || p_format==FORMAT_ATI1 || p_format==FORMAT_PVRTC4 || p_format==FORMAT_PVRTC4A || p_format==FORMAT_ETC || p_format==FORMAT_ETC2_R11 || p_format==FORMAT_ETC2_R11S || p_format==FORMAT_ETC2_RGB8 || p_format==FORMAT_ETC2_RGB8A1) + return 1; + else if (p_format==FORMAT_PVRTC2 || p_format==FORMAT_PVRTC2A) + return 2; + else + return 0; +} + void Image::_get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width,int &r_height) const { @@ -126,7 +226,7 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width int pixel_size = get_format_pixel_size(format); int pixel_rshift = get_format_pixel_rshift(format); int minw,minh; - _get_format_min_data_size(format,minw,minh); + get_format_min_pixel_size(format,minw,minh); for(int i=0;i<p_mipmap;i++) { int s = w*h; @@ -173,191 +273,76 @@ void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int & } -void Image::put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap){ - - ERR_FAIL_INDEX(p_mipmap,mipmaps+1); - int ofs,w,h; - _get_mipmap_offset_and_size(p_mipmap,ofs,w,h); - ERR_FAIL_INDEX(p_x,w); - ERR_FAIL_INDEX(p_y,h); - - DVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr=wp.ptr(); - - _put_pixelw(p_x,p_y,w,BColor(p_color.r*255,p_color.g*255,p_color.b*255,p_color.a*255),&data_ptr[ofs]); +int Image::get_width() const { + return width; } +int Image::get_height() const{ -Image::BColor Image::_get_pixel(int p_x,int p_y,const unsigned char *p_data,int p_data_size) const{ - - return _get_pixelw(p_x,p_y,width,p_data,p_data_size); + return height; } -Image::BColor Image::_get_pixelw(int p_x,int p_y,int p_width,const unsigned char *p_data,int p_data_size) const{ - int ofs=p_y*p_width+p_x; - BColor result(0,0,0,0); - switch(format) { - - case FORMAT_GRAYSCALE: { - - result=BColor(p_data[ofs],p_data[ofs],p_data[ofs],255.0); - } break; - case FORMAT_INTENSITY: { - - result=BColor(255,255,255,p_data[ofs]); - } break; - case FORMAT_GRAYSCALE_ALPHA: { - - result=BColor(p_data[ofs*2],p_data[ofs*2],p_data[ofs*2],p_data[ofs*2+1]); - - } break; - case FORMAT_RGB: { - - result=BColor(p_data[ofs*3],p_data[ofs*3+1],p_data[ofs*3+2]); - - } break; - case FORMAT_RGBA: { - - result=BColor(p_data[ofs*4],p_data[ofs*4+1],p_data[ofs*4+2],p_data[ofs*4+3]); - } break; - case FORMAT_INDEXED_ALPHA: { - - int pitch = 4; - const uint8_t* pal = &p_data[ p_data_size - pitch * 256 ]; - int idx = p_data[ofs]; - result=BColor(pal[idx * pitch + 0] , pal[idx * pitch + 1] , pal[idx * pitch + 2] , pal[idx * pitch + 3] ); - - } break; - case FORMAT_INDEXED: { - - int pitch = 3; - const uint8_t* pal = &p_data[ p_data_size - pitch * 256 ]; - int idx = p_data[ofs]; - result=BColor(pal[idx * pitch + 0] , pal[idx * pitch + 1] , pal[idx * pitch + 2] ,255); - } break; - case FORMAT_YUV_422: { - - int y, u, v; - if (p_x % 2) { - const uint8_t* yp = &p_data[p_width * 2 * p_y + p_x * 2]; - u = *(yp-1); - y = yp[0]; - v = yp[1]; - } else { - - const uint8_t* yp = &p_data[p_width * 2 * p_y + p_x * 2]; - y = yp[0]; - u = yp[1]; - v = yp[3]; - }; - - int32_t r = 1.164 * (y - 16) + 1.596 * (v - 128); - int32_t g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128); - int32_t b = 1.164 * (y - 16) + 2.018 * (u - 128); - result = BColor(CLAMP(r, 0, 255), CLAMP(g, 0, 255), CLAMP(b, 0, 255)); - } break; - case FORMAT_YUV_444: { - - uint8_t y, u, v; - const uint8_t* yp = &p_data[p_width * 3 * p_y + p_x * 3]; - y = yp[0]; - u = yp[1]; - v = yp[2]; - - int32_t r = 1.164 * (y - 16) + 1.596 * (v - 128); - int32_t g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128); - int32_t b = 1.164 * (y - 16) + 2.018 * (u - 128); - result = BColor(CLAMP(r, 0, 255), CLAMP(g, 0, 255), CLAMP(b, 0, 255)); - } break; - default:{} - - } - - return result; +bool Image::has_mipmaps() const { + return mipmaps; } -void Image::put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap) { - - ERR_FAIL_COND(format != FORMAT_INDEXED && format != FORMAT_INDEXED_ALPHA); - ERR_FAIL_INDEX(p_mipmap,mipmaps+1); - int ofs,w,h; - _get_mipmap_offset_and_size(p_mipmap,ofs,w,h); - ERR_FAIL_INDEX(p_x,w); - ERR_FAIL_INDEX(p_y,h); - - data.set(ofs + p_y * w + p_x, p_idx); -}; - -uint8_t Image::get_indexed_pixel(int p_x, int p_y,int p_mipmap) const { - - ERR_FAIL_COND_V(format != FORMAT_INDEXED && format != FORMAT_INDEXED_ALPHA, 0); - - ERR_FAIL_INDEX_V(p_mipmap,mipmaps+1,0); - int ofs,w,h; - _get_mipmap_offset_and_size(p_mipmap,ofs,w,h); - ERR_FAIL_INDEX_V(p_x,w,0); - ERR_FAIL_INDEX_V(p_y,h,0); - - - return data[ofs + p_y * w + p_x]; -}; - -void Image::set_pallete(const DVector<uint8_t>& p_data) { +int Image::get_mipmap_count() const { + if (mipmaps) + return get_image_required_mipmaps(width,height,format); + else + return 0; +} - int len = p_data.size(); - ERR_FAIL_COND(format != FORMAT_INDEXED && format != FORMAT_INDEXED_ALPHA); - ERR_FAIL_COND(format == FORMAT_INDEXED && len!=(256*3)); - ERR_FAIL_COND(format == FORMAT_INDEXED_ALPHA && len!=(256*4)); +//using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers +template<uint32_t read_bytes,bool read_alpha,uint32_t write_bytes,bool write_alpha,bool read_gray,bool write_gray> +static void _convert( int p_width,int p_height,const uint8_t* p_src,uint8_t* p_dst ){ - int ofs,w,h; - _get_mipmap_offset_and_size(mipmaps+1,ofs,w,h); - int pal_ofs = ofs; - data.resize(pal_ofs + p_data.size()); - DVector<uint8_t>::Write wp = data.write(); - unsigned char *dst=wp.ptr() + pal_ofs; + for(int y=0;y<p_height;y++) { + for(int x=0;x<p_width;x++) { - DVector<uint8_t>::Read r = p_data.read(); - const unsigned char *src=r.ptr(); + const uint8_t *rofs = &p_src[((y*p_width)+x)*(read_bytes+(read_alpha?1:0))]; + uint8_t *wofs = &p_dst[((y*p_width)+x)*(write_bytes+(write_alpha?1:0))]; - copymem(dst, src, len); -}; + uint8_t rgba[4]; -int Image::get_width() const { - - return width; -} -int Image::get_height() const{ - - return height; -} - -int Image::get_mipmaps() const { + if (read_gray) { + rgba[0]=rofs[0]; + rgba[1]=rofs[0]; + rgba[2]=rofs[0]; + } else { + for(uint32_t i=0;i<MAX(read_bytes,write_bytes);i++) { + rgba[i]=(i<read_bytes)?rofs[i]:0; + } + } - return mipmaps; -} + if (read_alpha || write_alpha) { + rgba[3]=read_alpha?rofs[read_bytes]:255; + } -Color Image::get_pixel(int p_x,int p_y,int p_mipmap) const { + if (write_gray) { + //TODO: not correct grayscale, should use fixed point version of actual weights + wofs[0]=uint8_t((uint16_t(rofs[0])+uint16_t(rofs[1])+uint16_t(rofs[2]))/3); + } else { + for(uint32_t i=0;i<write_bytes;i++) { + wofs[i]=rgba[i]; + } + } - ERR_FAIL_INDEX_V(p_mipmap,mipmaps+1,Color()); - int ofs,w,h; - _get_mipmap_offset_and_size(p_mipmap,ofs,w,h); - ERR_FAIL_INDEX_V(p_x,w,Color()); - ERR_FAIL_INDEX_V(p_y,h,Color()); + if (write_alpha) { + wofs[write_bytes]=rgba[3]; + } + } + } - int len = data.size(); - DVector<uint8_t>::Read r = data.read(); - const unsigned char*data_ptr=r.ptr(); - BColor c = _get_pixelw(p_x,p_y,w,&data_ptr[ofs],len); - return Color( c.r/255.0,c.g/255.0,c.b/255.0,c.a/255.0 ); } void Image::convert( Format p_new_format ){ @@ -368,22 +353,17 @@ void Image::convert( Format p_new_format ){ if (p_new_format==format) return; - if (format>=FORMAT_BC1 || p_new_format>=FORMAT_BC1) { - ERR_EXPLAIN("Cannot convert to <-> from compressed/custom image formats (for now)."); - ERR_FAIL(); - } - - if (p_new_format==FORMAT_INDEXED || p_new_format==FORMAT_INDEXED_ALPHA) { + if (format>=FORMAT_RGB565 || p_new_format>=FORMAT_RGB565) { - - return; + ERR_EXPLAIN("Cannot convert to <-> from non byte formats."); + ERR_FAIL(); } Image new_img(width,height,0,p_new_format); - int len=data.size(); +// int len=data.size(); DVector<uint8_t>::Read r = data.read(); DVector<uint8_t>::Write w = new_img.data.write(); @@ -391,35 +371,56 @@ void Image::convert( Format p_new_format ){ const uint8_t *rptr = r.ptr(); uint8_t *wptr = w.ptr(); - if (p_new_format==FORMAT_RGBA && format==FORMAT_INDEXED_ALPHA) { + int conversion_type = format | p_new_format<<8; + + switch(conversion_type) { + + case FORMAT_L8|(FORMAT_LA8<<8): _convert<1,false,1,true,true,true>( width, height,rptr, wptr ); break; + case FORMAT_L8|(FORMAT_R8<<8): _convert<1,false,1,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_L8|(FORMAT_RG8<<8): _convert<1,false,2,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_L8|(FORMAT_RGB8<<8): _convert<1,false,3,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_L8|(FORMAT_RGBA8<<8): _convert<1,false,3,true,true,false>( width, height,rptr, wptr ); break; + case FORMAT_LA8|(FORMAT_L8<<8): _convert<1,true,1,false,true,true>( width, height,rptr, wptr ); break; + case FORMAT_LA8|(FORMAT_R8<<8): _convert<1,true,1,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_LA8|(FORMAT_RG8<<8): _convert<1,true,2,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_LA8|(FORMAT_RGB8<<8): _convert<1,true,3,false,true,false>( width, height,rptr, wptr ); break; + case FORMAT_LA8|(FORMAT_RGBA8<<8): _convert<1,true,3,true,true,false>( width, height,rptr, wptr ); break; + case FORMAT_R8|(FORMAT_L8<<8): _convert<1,false,1,false,false,true>( width, height,rptr, wptr ); break; + case FORMAT_R8|(FORMAT_LA8<<8): _convert<1,false,1,true,false,true>( width, height,rptr, wptr ); break; + case FORMAT_R8|(FORMAT_RG8<<8): _convert<1,false,2,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_R8|(FORMAT_RGB8<<8): _convert<1,false,3,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_R8|(FORMAT_RGBA8<<8): _convert<1,false,3,true,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RG8|(FORMAT_L8<<8): _convert<2,false,1,false,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RG8|(FORMAT_LA8<<8): _convert<2,false,1,true,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RG8|(FORMAT_R8<<8): _convert<2,false,1,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RG8|(FORMAT_RGB8<<8): _convert<2,false,3,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RG8|(FORMAT_RGBA8<<8): _convert<2,false,3,true,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGB8|(FORMAT_L8<<8): _convert<3,false,1,false,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RGB8|(FORMAT_LA8<<8): _convert<3,false,1,true,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RGB8|(FORMAT_R8<<8): _convert<3,false,1,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGB8|(FORMAT_RG8<<8): _convert<3,false,2,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGB8|(FORMAT_RGBA8<<8): _convert<3,false,3,true,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGBA8|(FORMAT_L8<<8): _convert<3,true,1,false,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RGBA8|(FORMAT_LA8<<8): _convert<3,true,1,true,false,true>( width, height,rptr, wptr ); break; + case FORMAT_RGBA8|(FORMAT_R8<<8): _convert<3,true,1,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGBA8|(FORMAT_RG8<<8): _convert<3,true,2,false,false,false>( width, height,rptr, wptr ); break; + case FORMAT_RGBA8|(FORMAT_RGB8<<8): _convert<3,true,3,false,false,false>( width, height,rptr, wptr ); break; - //optimized unquantized form - int dataend = len-256*4; - const uint32_t *palpos = (const uint32_t*)&rptr[dataend]; - uint32_t *dst32 = (uint32_t *)wptr; - - for(int i=0;i<dataend;i++) - dst32[i]=palpos[rptr[i]]; //since this is read/write, endianness is not a problem - - } else { - - //this is temporary, must find a faster way to do it. - for(int i=0;i<width;i++) - for(int j=0;j<height;j++) - new_img._put_pixel(i,j,_get_pixel(i,j,rptr,len),wptr); } + r = DVector<uint8_t>::Read(); w = DVector<uint8_t>::Write(); - bool gen_mipmaps=mipmaps>0; + bool gen_mipmaps=mipmaps; + +// mipmaps=false; *this=new_img; if (gen_mipmaps) generate_mipmaps(); - } Image::Format Image::get_format() const{ @@ -460,13 +461,13 @@ static void _scale_cubic(const uint8_t* p_src, uint8_t* p_dst, uint32_t p_src_wi int xmax = width - 1; // temporary pointer - for ( int y = 0; y < p_dst_height; y++ ) { + for ( uint32_t 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++ ) { + for ( uint32_t x = 0; x < p_dst_width; x++ ) { // X coordinates ox = (double) x * xfac - 0.5f; ox1 = (int) ox; @@ -650,10 +651,6 @@ void Image::resize( int p_width, int p_height, Interpolation p_interpolation ) { Image dst( p_width, p_height, 0, format ); - if (format==FORMAT_INDEXED) - p_interpolation=INTERPOLATE_NEAREST; - - DVector<uint8_t>::Read r = data.read(); const unsigned char*r_ptr=r.ptr(); @@ -722,18 +719,33 @@ void Image::crop( int p_width, int p_height ) { if (p_width==width && p_height==height) return; + uint8_t pdata[16]; //largest is 16 + uint32_t pixel_size = get_format_pixel_size(format); + Image dst( p_width, p_height,0, format ); + { + DVector<uint8_t>::Read r = data.read(); + DVector<uint8_t>::Write w = dst.data.write(); - for (int y=0;y<p_height;y++) { + for (int y=0;y<p_height;y++) { - for (int x=0;x<p_width;x++) { + for (int x=0;x<p_width;x++) { - Color col = (x>=width || y>=height)? Color() : get_pixel(x,y); - dst.put_pixel(x,y,col); + if ((x>=width || y>=height)) { + for(uint32_t i=0;i<pixel_size;i++) + pdata[i]=0; + } else { + _get_pixelb(x,y,pixel_size,r.ptr(),pdata); + } + + + dst._put_pixelb(x,y,pixel_size,w.ptr(),pdata); + } } } + if (mipmaps>0) dst.generate_mipmaps(); *this=dst; @@ -754,18 +766,28 @@ void Image::flip_y() { + { + DVector<uint8_t>::Write w = data.write(); + uint8_t up[16]; + uint8_t down[16]; + uint32_t pixel_size = get_format_pixel_size(format); - for (int y=0;y<(height/2);y++) { + for (int y=0;y<height;y++) { - for (int x=0;x<width;x++) { + for (int x=0;x<width;x++) { - Color up = get_pixel(x,y); - Color down = get_pixel(x,height-y-1); - put_pixel(x,y,down); - put_pixel(x,height-y-1,up); + _get_pixelb(x,y,pixel_size,w.ptr(),up); + _get_pixelb(x,height-y-1,pixel_size,w.ptr(),down); + + _put_pixelb(x,height-y-1,pixel_size,w.ptr(),up); + _put_pixelb(x,y,pixel_size,w.ptr(),down); + + } } } + + if (gm) generate_mipmaps();; @@ -782,15 +804,25 @@ void Image::flip_x() { if (gm) clear_mipmaps();; - for (int y=0;y<(height/2);y++) { - for (int x=0;x<width;x++) { + { + DVector<uint8_t>::Write w = data.write(); + uint8_t up[16]; + uint8_t down[16]; + uint32_t pixel_size = get_format_pixel_size(format); + + for (int y=0;y<height;y++) { + + for (int x=0;x<width;x++) { - Color up = get_pixel(x,y); - Color down = get_pixel(width-x-1,y); - put_pixel(x,y,down); - put_pixel(width-x-1,y,up); + _get_pixelb(x,y,pixel_size,w.ptr(),up); + _get_pixelb(width-x-1,y,pixel_size,w.ptr(),down); + + _put_pixelb(width-x-1,y,pixel_size,w.ptr(),up); + _put_pixelb(x,y,pixel_size,w.ptr(),down); + + } } } @@ -809,15 +841,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format,int &r int pixsize=get_format_pixel_size(p_format); int pixshift=get_format_pixel_rshift(p_format); int minw,minh; - _get_format_min_data_size(p_format,minw,minh); - - - switch(p_format) { - - case FORMAT_INDEXED: pixsize=1; size=256*3; break; - case FORMAT_INDEXED_ALPHA: pixsize=1; size=256*4;break; - default: {} - } ; + get_format_min_pixel_size(p_format,minw,minh); while(true) { @@ -849,20 +873,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format,int &r bool Image::_can_modify(Format p_format) const { - switch(p_format) { - - //these are OK - case FORMAT_GRAYSCALE: - case FORMAT_INTENSITY: - case FORMAT_GRAYSCALE_ALPHA: - case FORMAT_RGB: - case FORMAT_RGBA: - return true; - default: - return false; - } - - return false; + return p_format<FORMAT_RGB565; } template<int CC> @@ -903,16 +914,16 @@ static void _generate_po2_mipmap(const uint8_t* p_src, uint8_t* p_dst, uint32_t void Image::expand_x2_hq2x() { - ERR_FAIL_COND(format>=FORMAT_INDEXED); + ERR_FAIL_COND(!_can_modify(format)); Format current = format; - bool mipmaps=get_mipmaps(); - if (mipmaps) { + bool mm=has_mipmaps(); + if (mm) { clear_mipmaps(); } - if (current!=FORMAT_RGBA) - convert(FORMAT_RGBA); + if (current!=FORMAT_RGBA8) + convert(FORMAT_RGBA8); DVector<uint8_t> dest; dest.resize(width*2*height*2*4); @@ -930,7 +941,7 @@ void Image::expand_x2_hq2x() { data=dest; - if (current!=FORMAT_RGBA) + if (current!=FORMAT_RGBA8) convert(current); if (mipmaps) { @@ -941,7 +952,6 @@ void Image::expand_x2_hq2x() { void Image::shrink_x2() { - ERR_FAIL_COND(format==FORMAT_INDEXED || format==FORMAT_INDEXED_ALPHA); ERR_FAIL_COND( data.size()==0 ); @@ -964,7 +974,6 @@ void Image::shrink_x2() { copymem(w.ptr(),&r[ofs],new_size); } - mipmaps--; width/=2; height/=2; data=new_img; @@ -973,7 +982,7 @@ void Image::shrink_x2() { DVector<uint8_t> new_img; - ERR_FAIL_COND( format>=FORMAT_INDEXED ); + ERR_FAIL_COND( !_can_modify(format) ); int ps = get_format_pixel_size(format); new_img.resize((width/2)*(height/2)*ps); @@ -983,11 +992,12 @@ void Image::shrink_x2() { switch(format) { - case FORMAT_GRAYSCALE: - case FORMAT_INTENSITY: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width,height); break; - case FORMAT_GRAYSCALE_ALPHA: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width,height); break; - case FORMAT_RGB: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width,height); break; - case FORMAT_RGBA: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_L8: + case FORMAT_R8: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_LA8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_RG8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_RGB8: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_RGBA8: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width,height); break; default: {} } } @@ -999,7 +1009,7 @@ void Image::shrink_x2() { } } -Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { +Error Image::generate_mipmaps(bool p_keep_existing) { if (!_can_modify(format)) { ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats."); @@ -1007,11 +1017,13 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { } + int mmcount = get_mipmap_count(); + int from_mm=1; if (p_keep_existing) { - from_mm=mipmaps+1; + from_mm=mmcount+1; } - int size = _get_dst_image_size(width,height,format,mipmaps,p_mipmaps); + int size = _get_dst_image_size(width,height,format,mmcount); data.resize(size); @@ -1023,7 +1035,7 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { int prev_h=height; int prev_w=width; - for(int i=1;i<mipmaps;i++) { + for(int i=1;i<mmcount;i++) { int ofs,w,h; @@ -1033,11 +1045,12 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { switch(format) { - case FORMAT_GRAYSCALE: - case FORMAT_INTENSITY: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; - case FORMAT_GRAYSCALE_ALPHA: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; - case FORMAT_RGB: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; - case FORMAT_RGBA: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; + case FORMAT_L8: + case FORMAT_R8: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; + case FORMAT_LA8: + case FORMAT_RG8: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; + case FORMAT_RGB8: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; + case FORMAT_RGBA8: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h); break; default: {} } } @@ -1056,7 +1069,7 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { int prev_h=height; int prev_w=width; - for(int i=1;i<mipmaps;i++) { + for(int i=1;i<mmcount;i++) { int ofs,w,h; @@ -1066,11 +1079,12 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { switch(format) { - case FORMAT_GRAYSCALE: - case FORMAT_INTENSITY: _scale_bilinear<1>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; - case FORMAT_GRAYSCALE_ALPHA: _scale_bilinear<2>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; - case FORMAT_RGB: _scale_bilinear<3>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; - case FORMAT_RGBA: _scale_bilinear<4>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; + case FORMAT_L8: + case FORMAT_R8: _scale_bilinear<1>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; + case FORMAT_LA8: + case FORMAT_RG8: _scale_bilinear<2>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; + case FORMAT_RGB8:_scale_bilinear<3>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; + case FORMAT_RGBA8: _scale_bilinear<4>(&wp[prev_ofs], &wp[ofs], prev_w,prev_h,w,h); break; default: {} } } @@ -1083,85 +1097,25 @@ Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { } - - return OK; } void Image::clear_mipmaps() { - if (mipmaps==0) + if (!mipmaps) return; - if (format==FORMAT_CUSTOM) { - ERR_EXPLAIN("Cannot clear mipmaps in indexed, compressed or custom image formats."); - ERR_FAIL(); - - } - if (empty()) return; int ofs,w,h; _get_mipmap_offset_and_size(1,ofs,w,h); - int palsize = get_format_pallete_size(format); - DVector<uint8_t> pallete; - ERR_FAIL_COND(ofs+palsize > data.size()); //bug? - if (palsize) { - - pallete.resize(palsize); - DVector<uint8_t>::Read r = data.read(); - DVector<uint8_t>::Write w = pallete.write(); - - copymem(&w[0],&r[data.size()-palsize],palsize); - } + data.resize(ofs); - data.resize(ofs+palsize); - - if (palsize) { - - DVector<uint8_t>::Read r = pallete.read(); - DVector<uint8_t>::Write w = data.write(); - - copymem(&w[ofs],&r[0],palsize); - } - - mipmaps=0; + mipmaps=false; } -void Image::make_normalmap(float p_height_scale) { - - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot crop in indexed, compressed or custom image formats."); - ERR_FAIL(); - } - - ERR_FAIL_COND( empty() ); - - Image normalmap(width,height,0, FORMAT_RGB); - /* - for (int y=0;y<height;y++) { - for (int x=0;x<width;x++) { - - float center=get_pixel(x,y).gray()/255.0; - float up=(y>0)?get_pixel(x,y-1).gray()/255.0:center; - float down=(y<(height-1))?get_pixel(x,y+1).gray()/255.0:center; - float left=(x>0)?get_pixel(x-1,y).gray()/255.0:center; - float right=(x<(width-1))?get_pixel(x+1,y).gray()/255.0:center; - - - // uhm, how do i do this? .... - - Color result( (uint8_t)((normal.x+1.0)*127.0), (uint8_t)((normal.y+1.0)*127.0), (uint8_t)((normal.z+1.0)*127.0) ); - - normalmap.put_pixel( x, y, result ); - } - - } - */ - *this=normalmap; -} bool Image::empty() const { @@ -1186,32 +1140,30 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps,Format p_format width=p_width; height=p_height; - mipmaps=mm; + mipmaps=p_use_mipmaps; format=p_format; } -void Image::create(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data) { +void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const DVector<uint8_t>& p_data) { ERR_FAIL_INDEX(p_width-1,MAX_WIDTH); ERR_FAIL_INDEX(p_height-1,MAX_HEIGHT); - if (p_format < FORMAT_CUSTOM) { - int mm; - int size = _get_dst_image_size(p_width,p_height,p_format,mm,p_mipmaps); + int mm; + int size = _get_dst_image_size(p_width,p_height,p_format,mm,p_use_mipmaps); - if (size!=p_data.size()) { - ERR_EXPLAIN("Expected data size of "+itos(size)+" in Image::create()"); - ERR_FAIL_COND(p_data.size()!=size); - } - }; + if (size!=p_data.size()) { + ERR_EXPLAIN("Expected data size of "+itos(size)+" in Image::create()"); + ERR_FAIL_COND(p_data.size()!=size); + } height=p_height; width=p_width; format=p_format; data=p_data; - mipmaps=p_mipmaps; + mipmaps=p_use_mipmaps; } @@ -1220,7 +1172,7 @@ void Image::create( const char ** p_xpm ) { int size_width,size_height; int pixelchars=0; - mipmaps=0; + mipmaps=false; bool has_alpha=false; enum Status { @@ -1235,6 +1187,8 @@ void Image::create( const char ** p_xpm ) { HashMap<String,Color> colormap; int colormap_size; + uint32_t pixel_size; + DVector<uint8_t>::Write w; while (status!=DONE) { @@ -1327,7 +1281,9 @@ void Image::create( const char ** p_xpm ) { if (line==colormap_size) { status=READING_PIXELS; - create(size_width,size_height,0,has_alpha?FORMAT_RGBA:FORMAT_RGB); + create(size_width,size_height,0,has_alpha?FORMAT_RGBA8:FORMAT_RGB8); + w=data.write(); + pixel_size=has_alpha?4:3; } } break; case READING_PIXELS: { @@ -1341,7 +1297,11 @@ void Image::create( const char ** p_xpm ) { Color *colorptr = colormap.getptr(pixelstr); ERR_FAIL_COND(!colorptr); - put_pixel(x,y,*colorptr); + uint8_t pixel[4]; + for(uint32_t i=0;i<pixel_size;i++) { + pixel[i]=CLAMP((*colorptr)[i]*255,0,255); + } + _put_pixelb(x,y,pixel_size,w.ptr(),pixel); } @@ -1382,9 +1342,8 @@ void Image::create( const char ** p_xpm ) { bool Image::is_invisible() const { - if (format==FORMAT_GRAYSCALE || - format==FORMAT_RGB || - format==FORMAT_INDEXED) + if (format==FORMAT_L8 || + format==FORMAT_RGB8 || format==FORMAT_RG8) return false; int len = data.size(); @@ -1392,8 +1351,6 @@ bool Image::is_invisible() const { if (len==0) return true; - if (format >= FORMAT_YUV_422 && format <= FORMAT_YUV_444) - return false; int w,h; _get_mipmap_offset_and_size(1,len,w,h); @@ -1404,13 +1361,8 @@ bool Image::is_invisible() const { bool detected=false; switch(format) { - case FORMAT_INTENSITY: { - for(int i=0;i<len;i++) { - DETECT_NON_ALPHA(data_ptr[i]); - } - } break; - case FORMAT_GRAYSCALE_ALPHA: { + case FORMAT_LA8: { for(int i=0;i<(len>>1);i++) { @@ -1418,25 +1370,18 @@ bool Image::is_invisible() const { } } break; - case FORMAT_RGBA: { + case FORMAT_RGBA8: { for(int i=0;i<(len>>2);i++) { DETECT_NON_ALPHA(data_ptr[(i<<2)+3]) } } break; - case FORMAT_INDEXED: { - return false; - } break; - case FORMAT_INDEXED_ALPHA: { - - return false; - } break; - case FORMAT_PVRTC2_ALPHA: - case FORMAT_PVRTC4_ALPHA: - case FORMAT_BC2: - case FORMAT_BC3: { + case FORMAT_PVRTC2A: + case FORMAT_PVRTC4A: + case FORMAT_DXT3: + case FORMAT_DXT5: { detected=true; } break; default: {} @@ -1447,19 +1392,12 @@ bool Image::is_invisible() const { Image::AlphaMode Image::detect_alpha() const { - if (format==FORMAT_GRAYSCALE || - format==FORMAT_RGB || - format==FORMAT_INDEXED) - return ALPHA_NONE; int len = data.size(); if (len==0) return ALPHA_NONE; - if (format >= FORMAT_YUV_422 && format <= FORMAT_YUV_444) - return ALPHA_NONE; - int w,h; _get_mipmap_offset_and_size(1,len,w,h); @@ -1470,13 +1408,8 @@ Image::AlphaMode Image::detect_alpha() const { bool detected=false; switch(format) { - case FORMAT_INTENSITY: { - for(int i=0;i<len;i++) { - DETECT_ALPHA(data_ptr[i]); - } - } break; - case FORMAT_GRAYSCALE_ALPHA: { + case FORMAT_LA8: { for(int i=0;i<(len>>1);i++) { @@ -1484,25 +1417,17 @@ Image::AlphaMode Image::detect_alpha() const { } } break; - case FORMAT_RGBA: { + case FORMAT_RGBA8: { for(int i=0;i<(len>>2);i++) { DETECT_ALPHA(data_ptr[(i<<2)+3]) } - } break; - case FORMAT_INDEXED: { - - return ALPHA_NONE; - } break; - case FORMAT_INDEXED_ALPHA: { - - return ALPHA_BLEND; - } break; - case FORMAT_PVRTC2_ALPHA: - case FORMAT_PVRTC4_ALPHA: - case FORMAT_BC2: - case FORMAT_BC3: { + } break; + case FORMAT_PVRTC2A: + case FORMAT_PVRTC4A: + case FORMAT_DXT3: + case FORMAT_DXT5: { detected=true; } break; default: {} @@ -1528,7 +1453,7 @@ Error Image::save_png(const String& p_path) { return ERR_UNAVAILABLE; return save_png_func(p_path, *this); -}; +} bool Image::operator==(const Image& p_image) const { @@ -1541,84 +1466,7 @@ bool Image::operator==(const Image& p_image) const { } -int Image::get_format_pixel_size(Format p_format) { - - switch(p_format) { - case FORMAT_GRAYSCALE: { - - return 1; - } break; - case FORMAT_INTENSITY: { - - return 1; - } break; - case FORMAT_GRAYSCALE_ALPHA: { - - return 2; - } break; - case FORMAT_RGB: { - - return 3; - } break; - case FORMAT_RGBA: { - - return 4; - } break; - case FORMAT_INDEXED: { - return 1; - } break; - case FORMAT_INDEXED_ALPHA: { - - return 1; - } break; - case FORMAT_BC1: - case FORMAT_BC2: - case FORMAT_BC3: - case FORMAT_BC4: - case FORMAT_BC5: { - - return 1; - } break; - case FORMAT_PVRTC2: - case FORMAT_PVRTC2_ALPHA: { - - return 1; - } break; - case FORMAT_PVRTC4: - case FORMAT_PVRTC4_ALPHA: { - - return 1; - } break; - case FORMAT_ATC: - case FORMAT_ATC_ALPHA_EXPLICIT: - case FORMAT_ATC_ALPHA_INTERPOLATED: { - - return 1; - } break; - case FORMAT_ETC: { - - return 1; - } break; - case FORMAT_YUV_422: { - return 2; - }; - case FORMAT_YUV_444: { - return 3; - } break; - case FORMAT_CUSTOM: { - - ERR_EXPLAIN("pixel size requested for custom image format, and it's unknown obviously"); - ERR_FAIL_V(1); - } break; - default:{ - ERR_EXPLAIN("Cannot obtain pixel size from this format"); - ERR_FAIL_V(1); - - } - } - return 0; -} int Image::get_image_data_size(int p_width, int p_height, Format p_format,int p_mipmaps) { @@ -1635,105 +1483,12 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format } -void Image::_get_format_min_data_size(Format p_format,int &r_w, int &r_h) { - - - switch(p_format) { - case FORMAT_BC1: - case FORMAT_BC2: - case FORMAT_BC3: - case FORMAT_BC4: - case FORMAT_BC5: { - r_w=4; - r_h=4; - } break; - case FORMAT_PVRTC2: - case FORMAT_PVRTC2_ALPHA: { - - r_w=16; - r_h=8; - } break; - case FORMAT_PVRTC4_ALPHA: - case FORMAT_PVRTC4: { - - r_w=8; - r_h=8; - } break; - case FORMAT_ATC: - case FORMAT_ATC_ALPHA_EXPLICIT: - case FORMAT_ATC_ALPHA_INTERPOLATED: { - - r_w=8; - r_h=8; - - } break; - - case FORMAT_ETC: { - - r_w=4; - r_h=4; - } break; - default: { - r_w=1; - r_h=1; - } break; - } - -} - - -int Image::get_format_pixel_rshift(Format p_format) { - - if (p_format==FORMAT_BC1 || p_format==FORMAT_BC4 || p_format==FORMAT_ATC || p_format==FORMAT_PVRTC4 || p_format==FORMAT_PVRTC4_ALPHA || p_format==FORMAT_ETC) - return 1; - else if (p_format==FORMAT_PVRTC2 || p_format==FORMAT_PVRTC2_ALPHA) - return 2; - else - return 0; -} - -int Image::get_format_pallete_size(Format p_format) { - - switch(p_format) { - case FORMAT_GRAYSCALE: { - - return 0; - } break; - case FORMAT_INTENSITY: { - - return 0; - } break; - case FORMAT_GRAYSCALE_ALPHA: { - - return 0; - } break; - case FORMAT_RGB: { - - return 0; - } break; - case FORMAT_RGBA: { - - return 0; - } break; - case FORMAT_INDEXED: { - - return 3*256; - } break; - case FORMAT_INDEXED_ALPHA: { - - return 4*256; - } break; - default:{} - } - return 0; -} Error Image::_decompress_bc() { - print_line("decompressing bc"); int wd=width,ht=height; if (wd%4!=0) { @@ -1745,7 +1500,7 @@ Error Image::_decompress_bc() { int mm; - int size = _get_dst_image_size(wd,ht,FORMAT_RGBA,mm,mipmaps); + int size = _get_dst_image_size(wd,ht,FORMAT_RGBA8,mm); DVector<uint8_t> newdata; newdata.resize(size); @@ -1762,7 +1517,7 @@ Error Image::_decompress_bc() { switch(format) { - case FORMAT_BC1: { + case FORMAT_DXT1: { int len = (wd*ht)/16; uint8_t* dst=&w[wofs]; @@ -1788,8 +1543,8 @@ Error Image::_decompress_bc() { col_b|=src[2]; uint8_t table[4][4]={ - { (col_a>>11)<<3, ((col_a>>5)&0x3f)<<2, ((col_a)&0x1f)<<3, 255 }, - { (col_b>>11)<<3, ((col_b>>5)&0x3f)<<2, ((col_b)&0x1f)<<3, 255 }, + { uint8_t((col_a>>11)<<3), uint8_t(((col_a>>5)&0x3f)<<2),uint8_t(((col_a)&0x1f)<<3), 255 }, + { uint8_t((col_b>>11)<<3), uint8_t(((col_b>>5)&0x3f)<<2),uint8_t(((col_b)&0x1f)<<3), 255 }, {0,0,0,255}, {0,0,0,255} }; @@ -1841,7 +1596,7 @@ Error Image::_decompress_bc() { ht/=2; } break; - case FORMAT_BC2: { + case FORMAT_DXT3: { int len = (wd*ht)/16; uint8_t* dst=&w[wofs]; @@ -1885,8 +1640,9 @@ Error Image::_decompress_bc() { col_b|=src[8+2]; uint8_t table[4][4]={ - { (col_a>>11)<<3, ((col_a>>5)&0x3f)<<2, ((col_a)&0x1f)<<3, 255 }, - { (col_b>>11)<<3, ((col_b>>5)&0x3f)<<2, ((col_b)&0x1f)<<3, 255 }, + { uint8_t((col_a>>11)<<3), uint8_t(((col_a>>5)&0x3f)<<2),uint8_t(((col_a)&0x1f)<<3), 255 }, + { uint8_t((col_b>>11)<<3), uint8_t(((col_b>>5)&0x3f)<<2),uint8_t(((col_b)&0x1f)<<3), 255 }, + {0,0,0,255}, {0,0,0,255} }; @@ -1933,7 +1689,7 @@ Error Image::_decompress_bc() { ht/=2; } break; - case FORMAT_BC3: { + case FORMAT_DXT5: { int len = (wd*ht)/16; uint8_t* dst=&w[wofs]; @@ -2001,9 +1757,10 @@ Error Image::_decompress_bc() { col_b<<=8; col_b|=src[8+2]; - uint8_t table[4][4]={ - { (col_a>>11)<<3, ((col_a>>5)&0x3f)<<2, ((col_a)&0x1f)<<3, 255 }, - { (col_b>>11)<<3, ((col_b>>5)&0x3f)<<2, ((col_b)&0x1f)<<3, 255 }, + uint8_t table[4][4]={ + { uint8_t((col_a>>11)<<3), uint8_t(((col_a>>5)&0x3f)<<2),uint8_t(((col_a)&0x1f)<<3), 255 }, + { uint8_t((col_b>>11)<<3), uint8_t(((col_b>>5)&0x3f)<<2),uint8_t(((col_b)&0x1f)<<3), 255 }, + {0,0,0,255}, {0,0,0,255} }; @@ -2061,18 +1818,19 @@ Error Image::_decompress_bc() { r=DVector<uint8_t>::Read(); data=newdata; - format=FORMAT_RGBA; + format=FORMAT_RGBA8; if (wd!=width || ht!=height) { - //todo, crop - width=wd; - height=ht; + + SWAP(width,wd); + SWAP(height,ht); + crop(wd,ht); } return OK; } bool Image::is_compressed() const { - return format>=FORMAT_BC1; + return format>=FORMAT_RGB565; } @@ -2085,12 +1843,14 @@ Image Image::decompressed() const { Error Image::decompress() { - if (format>=FORMAT_BC1 && format<=FORMAT_BC5 ) + if (format>=FORMAT_DXT1 && format<=FORMAT_ATI2 ) _decompress_bc();//_image_decompress_bc(this); - else if (format>=FORMAT_PVRTC2 && format<=FORMAT_PVRTC4_ALPHA && _image_decompress_pvrtc) + else if (format>=FORMAT_PVRTC2 && format<=FORMAT_PVRTC4A&& _image_decompress_pvrtc) _image_decompress_pvrtc(this); else if (format==FORMAT_ETC && _image_decompress_etc) _image_decompress_etc(this); + else if (format>=FORMAT_ETC2_R11 && format<=FORMAT_ETC2_RGB8A1 && _image_decompress_etc) + _image_decompress_etc2(this); else return ERR_UNAVAILABLE; return OK; @@ -2101,7 +1861,12 @@ Error Image::compress(CompressMode p_mode) { switch(p_mode) { - case COMPRESS_BC: { + case COMPRESS_16BIT: { + + //ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); + //_image_compress_bc_func(this); + } break; + case COMPRESS_S3TC: { ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); _image_compress_bc_func(this); @@ -2121,6 +1886,11 @@ Error Image::compress(CompressMode p_mode) { ERR_FAIL_COND_V(!_image_compress_etc_func, ERR_UNAVAILABLE); _image_compress_etc_func(this); } break; + case COMPRESS_ETC2: { + + ERR_FAIL_COND_V(!_image_compress_etc_func, ERR_UNAVAILABLE); + _image_compress_etc_func(this); + } break; } @@ -2133,14 +1903,14 @@ Image Image::compressed(int p_mode) { ret.compress((Image::CompressMode)p_mode); return ret; -}; +} Image::Image(const char **p_xpm) { width=0; height=0; - mipmaps=0; - format=FORMAT_GRAYSCALE; + mipmaps=false; + format=FORMAT_L8; create(p_xpm); } @@ -2150,37 +1920,28 @@ Image::Image(int p_width, int p_height,bool p_use_mipmaps, Format p_format) { width=0; height=0; - mipmaps=0; - format=FORMAT_GRAYSCALE; + mipmaps=p_use_mipmaps; + format=FORMAT_L8; create(p_width,p_height,p_use_mipmaps,p_format); } -Image::Image(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data) { +Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const DVector<uint8_t>& p_data) { width=0; height=0; - mipmaps=0; - format=FORMAT_GRAYSCALE; + mipmaps=p_mipmaps; + format=FORMAT_L8; create(p_width,p_height,p_mipmaps,p_format,p_data); } -Image Image::brushed(const Image& p_src, const Image& p_brush, const Point2& p_dest) const { - - Image img = *this; - img.brush_transfer(p_src,p_brush,p_dest); - return img; -} - Rect2 Image::get_used_rect() const { - if (format==FORMAT_GRAYSCALE || - format==FORMAT_RGB || - format==FORMAT_INDEXED || format>FORMAT_INDEXED_ALPHA) + if (format!=FORMAT_LA8 && format!=FORMAT_RGBA8) return Rect2(Point2(),Size2(width,height)); int len = data.size(); @@ -2188,16 +1949,18 @@ Rect2 Image::get_used_rect() const { if (len==0) return Rect2(); - int data_size = len; + //int data_size = len; DVector<uint8_t>::Read r = data.read(); const unsigned char *rptr=r.ptr(); + int ps = format==FORMAT_LA8?2:4; int minx=0xFFFFFF,miny=0xFFFFFFF; int maxx=-1,maxy=-1; - for(int i=0;i<width;i++) { - for(int j=0;j<height;j++) { + for(int j=0;j<height;j++) { + for(int i=0;i<width;i++) { + - bool opaque = _get_pixel(i,j,rptr,data_size).a>2; + bool opaque = rptr[(j*width+i)*ps+(ps-1)]>2; if (!opaque) continue; if (i>maxx) @@ -2225,101 +1988,47 @@ Image Image::get_rect(const Rect2& p_area) const { img.blit_rect(*this, p_area, Point2(0, 0)); return img; -}; - -void Image::brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest) { - - - ERR_FAIL_COND( width != p_src.width || height !=p_src.height); - - int dst_data_size = data.size(); - DVector<uint8_t>::Write wp = data.write(); - unsigned char *dst_data_ptr=wp.ptr(); - - - int src_data_size = p_src.data.size(); - DVector<uint8_t>::Read rp = p_src.data.read(); - const unsigned char *src_data_ptr=rp.ptr(); - - int brush_data_size = p_brush.data.size(); - DVector<uint8_t>::Read bp = p_brush.data.read(); - const unsigned char *src_brush_ptr=bp.ptr(); - - int bw = p_brush.get_width(); - int bh = p_brush.get_height(); - int dx=p_dest.x; - int dy=p_dest.y; - - for(int i=dy;i<dy+bh;i++) { - - if (i<0 || i >= height) - continue; - for(int j=dx;j<dx+bw;j++) { - - if (j<0 || j>=width) - continue; - - BColor src = p_src._get_pixel(j,i,src_data_ptr,src_data_size); - BColor dst = _get_pixel(j,i,dst_data_ptr,dst_data_size); - BColor brush = p_brush._get_pixel(j-dx,i-dy,src_brush_ptr,brush_data_size); - uint32_t mult = brush.r; - dst.r = dst.r + (((int32_t(src.r)-int32_t(dst.r))*mult)>>8); - dst.g = dst.g + (((int32_t(src.g)-int32_t(dst.g))*mult)>>8); - dst.b = dst.b + (((int32_t(src.b)-int32_t(dst.b))*mult)>>8); - dst.a = dst.a + (((int32_t(src.a)-int32_t(dst.a))*mult)>>8); - _put_pixel(j,i,dst,dst_data_ptr); - } - } } - void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest) { int dsize=data.size(); int srcdsize=p_src.data.size(); ERR_FAIL_COND( dsize==0 ); ERR_FAIL_COND( srcdsize==0 ); + ERR_FAIL_COND( format!=p_src.format ); + Rect2i local_src_rect = Rect2i(0,0,width,height).clip( Rect2i(p_dest+p_src_rect.pos,p_src_rect.size) ); - Rect2 rrect = Rect2(0,0,p_src.width,p_src.height).clip(p_src_rect); + if (local_src_rect.size.x<=0 || local_src_rect.size.y<=0) + return; + Rect2i src_rect( p_src_rect.pos + ( local_src_rect.pos - p_dest), local_src_rect.size ); DVector<uint8_t>::Write wp = data.write(); - unsigned char *dst_data_ptr=wp.ptr(); + uint8_t *dst_data_ptr=wp.ptr(); DVector<uint8_t>::Read rp = p_src.data.read(); - const unsigned char *src_data_ptr=rp.ptr(); - - if ((format==FORMAT_INDEXED || format == FORMAT_INDEXED_ALPHA) && (p_src.format==FORMAT_INDEXED || p_src.format == FORMAT_INDEXED_ALPHA)) { - - Point2i desti(p_dest.x, p_dest.y); - Point2i srci(rrect.pos.x, rrect.pos.y); + const uint8_t *src_data_ptr=rp.ptr(); - for(int i=0;i<rrect.size.y;i++) { + int pixel_size=get_format_pixel_size(format); - if (i<0 || i >= height) - continue; - for(int j=0;j<rrect.size.x;j++) { - - if (j<0 || j>=width) - continue; + for(int i=0;i<src_rect.size.y;i++) { - dst_data_ptr[width * (desti.y + i) + desti.x + j] = src_data_ptr[p_src.width * (srci.y+i) + srci.x+j]; - } - } - } else { + for(int j=0;j<src_rect.size.x;j++) { - for(int i=0;i<rrect.size.y;i++) { + int src_x = src_rect.pos.x+j; + int src_y = src_rect.pos.y+i; - if (i<0 || i >= height) - continue; - for(int j=0;j<rrect.size.x;j++) { + int dst_x = local_src_rect.pos.x+j; + int dst_y = local_src_rect.pos.y+i; - if (j<0 || j>=width) - continue; + const uint8_t *src = &src_data_ptr[ (src_y*p_src.width+src_x)*pixel_size]; + uint8_t *dst = &dst_data_ptr[ (dst_y*width+dst_x)*pixel_size]; - _put_pixel(p_dest.x+j,p_dest.y+i,p_src._get_pixel(rrect.pos.x+j,rrect.pos.y+i,src_data_ptr,srcdsize),dst_data_ptr); + for(int k=0;k<pixel_size;k++) { + dst[k]=src[k]; } } } @@ -2334,9 +2043,11 @@ void (*Image::_image_compress_bc_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL; void (*Image::_image_compress_etc_func)(Image *)=NULL; +void (*Image::_image_compress_etc2_func)(Image *)=NULL; void (*Image::_image_decompress_pvrtc)(Image *)=NULL; void (*Image::_image_decompress_bc)(Image *)=NULL; void (*Image::_image_decompress_etc)(Image *)=NULL; +void (*Image::_image_decompress_etc2)(Image *)=NULL; DVector<uint8_t> (*Image::lossy_packer)(const Image& ,float )=NULL; Image (*Image::lossy_unpacker)(const DVector<uint8_t>& )=NULL; @@ -2352,7 +2063,7 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) { void Image::normalmap_to_xy() { - convert(Image::FORMAT_RGBA); + convert(Image::FORMAT_RGBA8); { int len = data.size()/4; @@ -2367,7 +2078,7 @@ void Image::normalmap_to_xy() { } } - convert(Image::FORMAT_GRAYSCALE_ALPHA); + convert(Image::FORMAT_LA8); } void Image::srgb_to_linear() { @@ -2378,9 +2089,9 @@ void Image::srgb_to_linear() { static const uint8_t srgb2lin[256]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 148, 150, 152, 153, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 188, 190, 192, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 248, 250, 252}; - ERR_FAIL_COND( format!=FORMAT_RGB && format!=FORMAT_RGBA ); + ERR_FAIL_COND( format!=FORMAT_RGB8 && format!=FORMAT_RGBA8 ); - if (format==FORMAT_RGBA) { + if (format==FORMAT_RGBA8) { int len = data.size()/4; DVector<uint8_t>::Write wp = data.write(); @@ -2393,7 +2104,7 @@ void Image::srgb_to_linear() { data_ptr[(i<<2)+2]=srgb2lin[ data_ptr[(i<<2)+2] ]; } - } else if (format==FORMAT_RGB) { + } else if (format==FORMAT_RGB8) { int len = data.size()/3; DVector<uint8_t>::Write wp = data.write(); @@ -2414,7 +2125,7 @@ void Image::premultiply_alpha() { if (data.size()==0) return; - if (format!=FORMAT_RGBA) + if (format!=FORMAT_RGBA8) return; //not needed DVector<uint8_t>::Write wp = data.write(); @@ -2424,11 +2135,11 @@ void Image::premultiply_alpha() { for(int i=0;i<height;i++) { for(int j=0;j<width;j++) { - BColor bc = _get_pixel(j,i,data_ptr,0); - bc.r=(int(bc.r)*int(bc.a))>>8; - bc.g=(int(bc.g)*int(bc.a))>>8; - bc.b=(int(bc.b)*int(bc.a))>>8; - _put_pixel(j,i,bc,data_ptr); + uint8_t *ptr = &data_ptr[(i*width+j)*4]; + + ptr[0]=(uint16_t(ptr[0])*uint16_t(ptr[3]))>>8; + ptr[1]=(uint16_t(ptr[1])*uint16_t(ptr[3]))>>8; + ptr[2]=(uint16_t(ptr[2])*uint16_t(ptr[3]))>>8; } } } @@ -2438,12 +2149,12 @@ void Image::fix_alpha_edges() { if (data.size()==0) return; - if (format!=FORMAT_RGBA) + if (format!=FORMAT_RGBA8) return; //not needed DVector<uint8_t> dcopy = data; DVector<uint8_t>::Read rp = data.read(); - const uint8_t *rptr=rp.ptr(); + const uint8_t *srcptr=rp.ptr(); DVector<uint8_t>::Write wp = data.write(); unsigned char *data_ptr=wp.ptr(); @@ -2455,13 +2166,16 @@ void Image::fix_alpha_edges() { for(int i=0;i<height;i++) { for(int j=0;j<width;j++) { - BColor bc = _get_pixel(j,i,rptr,0); - if (bc.a>=alpha_treshold) + const uint8_t *rptr = &srcptr[(i*width+j)*4]; + uint8_t *wptr = &data_ptr[(i*width+j)*4]; + + if (rptr[3]>=alpha_treshold) continue; int closest_dist=max_dist; - BColor closest_color; - closest_color.a=bc.a; + uint8_t closest_color[3]; + + int from_x = MAX(0,j-max_radius); int to_x = MIN(width-1,j+max_radius); int from_y = MAX(0,i-max_radius); @@ -2476,22 +2190,25 @@ void Image::fix_alpha_edges() { if (dist>=closest_dist) continue; - const uint8_t * rp = &rptr[(k*width+l)<<2]; + const uint8_t * rp = &srcptr[(k*width+l)<<2]; if (rp[3]<alpha_treshold) continue; - closest_dist=dist; - closest_color.r=rp[0]; - closest_color.g=rp[1]; - closest_color.b=rp[2]; + closest_color[0]=rp[0]; + closest_color[1]=rp[1]; + closest_color[2]=rp[2]; } } - if (closest_dist!=max_dist) - _put_pixel(j,i,closest_color,data_ptr); + if (closest_dist!=max_dist) { + + wptr[0]=closest_color[0]; + wptr[1]=closest_color[1]; + wptr[2]=closest_color[2]; + } } } @@ -2508,8 +2225,8 @@ Image::Image(const uint8_t* p_mem_png_jpg, int p_len) { width=0; height=0; - mipmaps=0; - format=FORMAT_GRAYSCALE; + mipmaps=false; + format=FORMAT_L8; if (_png_mem_loader_func) { *this = _png_mem_loader_func(p_mem_png_jpg,p_len); @@ -2525,8 +2242,8 @@ Image::Image() { width=0; height=0; - mipmaps=0; - format = FORMAT_GRAYSCALE; + mipmaps=false; + format = FORMAT_L8; } Image::~Image() { |