Hi,
I want to create down-scaled Bitmaps ( original Bitmap loaded from asset) with high quality comparable to the quality of bitmaps scaled with professional software like Paint.net (in Paint.NET the algorithm for scaling is choosen in a field called Interpolation. The highest setting uses supersampling)?
I understand how to implement supersampling for anti-aliasing. For anti-aliasing-purpose the original image is rendered in higher resolution and then gets downsampled. For Example to get a target image of 100x100 you would render the scene to 200x200 and then downsampling it with a 2x2 grid.
But, how the algorithm can handle downsampling from let's say 400x400 to 175x175 for scaling-purpose. The grid must be ~ 2.285x2.285 in this case. So how can supersampling be implemented for scaling-purpose?
I tried this code:
The following image shows the same 100x100 bitmap scaled to 54x54. The left one is scaled by Paint.Net and the right one by my algorithm. Doesn't look good for my implementation... How can I improve my code?
thx & regards
PS: I work with Java on Android, but I think my question is more generel then android-specific..
EDIT:
I changed my code + added a bit blur to the bitmap before scaling like amnon.owed suggests. The result is pretty good on my smartphone. Even a bit better then the "Paint.Net-version" !
I want to create down-scaled Bitmaps ( original Bitmap loaded from asset) with high quality comparable to the quality of bitmaps scaled with professional software like Paint.net (in Paint.NET the algorithm for scaling is choosen in a field called Interpolation. The highest setting uses supersampling)?
I understand how to implement supersampling for anti-aliasing. For anti-aliasing-purpose the original image is rendered in higher resolution and then gets downsampled. For Example to get a target image of 100x100 you would render the scene to 200x200 and then downsampling it with a 2x2 grid.
But, how the algorithm can handle downsampling from let's say 400x400 to 175x175 for scaling-purpose. The grid must be ~ 2.285x2.285 in this case. So how can supersampling be implemented for scaling-purpose?
I tried this code:
- public static Bitmap downscaleBitmap(Bitmap src, int targetWidth, int targetHeight, int off){
- float r = (src.getWidth()-off)/(float)targetWidth;
- float s = (src.getHeight()-off)/(float)targetHeight;
- Bitmap target = Bitmap.createBitmap(Math.round(src.getWidth()/r), Math.round(src.getHeight()/s), Config.ARGB_8888);
- r = src.getWidth()/(float)target.getWidth();
- s = src.getHeight()/(float)target.getHeight();
- int argb;
- int red;
- int green;
- int blue;
- int alpha;
- float wx;
- float wy;
- float n;
- for(int i=0;i<target.getWidth();++i){
- for(int j=0;j<target.getHeight();++j){
- red = 0;
- green = 0;
- blue = 0;
- alpha = 0;
- n=0;
- for(int k =(int)(i*r);k<roundUp((i+1)*r);++k){
- if(k<i*r){
- wx = k-i*r+1;
- }else{
- if(k+1>(i+1)*r)
- wx = (i+1)*r-k;
- else
- wx = 1;
- }
- for(int l=(int)(j*s);l<roundUp((j+1)*s);++l){
- if(l<j*s){
- wy = l-j*s+1;
- }else{
- if(l+1>(j+1)*s)
- wy = (j+1)*s-l;
- else
- wy = 1;
- }
- n+=wy*wx;
- argb=src.getPixel(k, l);
- red += wx*wy*Color.red(argb);
- green += wx*wy*Color.green(argb);
- blue += wx*wy*Color.blue(argb);
- alpha += wx*wy*Color.alpha(argb);
- }
- }
- target.setPixel(i, j, Color.argb((int)(alpha/n), (int)(red/n), (int)(green/n), (int)(blue/n)));
- }
- }
- return target;
- }
The following image shows the same 100x100 bitmap scaled to 54x54. The left one is scaled by Paint.Net and the right one by my algorithm. Doesn't look good for my implementation... How can I improve my code?
thx & regards
PS: I work with Java on Android, but I think my question is more generel then android-specific..
EDIT:
I changed my code + added a bit blur to the bitmap before scaling like amnon.owed suggests. The result is pretty good on my smartphone. Even a bit better then the "Paint.Net-version" !
1