Recent

Author Topic: TResampleFilter rfBestQuality (BGRABitmapTypes)  (Read 690 times)

del

  • Full Member
  • ***
  • Posts: 200
TResampleFilter rfBestQuality (BGRABitmapTypes)
« on: April 14, 2021, 02:38:17 pm »
According to the comments in BGRABitmapTypes, rfBestQuality is the best quality among rfMitchell and rfSpline. Is it the best overall for upsizing interpolation? Better than rfLanczos4? I'm assuming that rfMitchell has some built-in anti-aliasing which makes it best for downsizing interpolation.

Code: Pascal  [Select][+][-]
  1. // rfMitchell: Mitchell filter, good for downsizing interpolation
  2. // rfSpline: Spline filter, good for upsizing interpolation, however slightly blurry
  3. // rfLanczos2: Lanczos with radius 2, blur is corrected
  4. // rfLanczos3: Lanczos with radius 3, high contrast
  5. // rfLanczos4: Lanczos with radius 4, high contrast
  6. // rfBestQuality: Best quality using rfMitchell or rfSpline
« Last Edit: April 14, 2021, 02:39:50 pm by del »

winni

  • Hero Member
  • *****
  • Posts: 2331
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #1 on: April 16, 2021, 08:18:39 pm »
Hi!

For downsizing Mitchell is the best filter.

For upsizing it depends on your needs.
For photographs Spline is the best.
But for technical drawings Lanzcos3 or 4 give better contrast.

Simple tests for upsizing:

Load a little icon into a BGRAbitmap and resize it to 512 x 512

Code: Pascal  [Select][+][-]
  1. var MyIcon : TBGRABitmap:
  2. ....
  3. MyIcon := TBGRAbitmap.create (FileName);
  4. MyIcon.resampleFilter := rfSpline; // or rfLanzos3 or ...
  5. BGRAReplace (MyIcon, MyIcon.resample (512,512));
  6. MyIcon.Draw (Image1.Canvas,0,0);
  7. MyIcon.free;
  8. ....
  9.  
  10.  
Winni



del

  • Full Member
  • ***
  • Posts: 200
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #2 on: April 17, 2021, 04:52:56 pm »
OK thanks. I've already implemented the function with TRadioGroup to pick all the different methods. I'm guessing the issue is sharpness vs artifacts. I'll do some experiments.

winni

  • Hero Member
  • *****
  • Posts: 2331
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #3 on: April 17, 2021, 06:56:22 pm »
Hi!

And here is the base for a hardrock test:

Just create a 2 x 2 Bitmap and fill it with 4 different colors.
And then resample it with the different filters.
And follow the differents gradients.

Code: Pascal  [Select][+][-]
  1. var tmp: TBGRA.Bitmap;
  2. ...
  3. tmp := TBGRAbitmap.create (2,2);
  4. tmp.setpixel(0,0,cssBlue);
  5. tmp.setpixel(0,1,cssRed);
  6. tmp.setpixel(1,0,cssYellow);
  7. tmp.setpixel(1,1,cssLime);
  8. tmp.resampleFilter := rfspline; // rfLancos2, ....
  9. BGRAreplace (tmp, tmp.resample(512,512));
  10. tmp.Draw(Image1.Canvas, 0,0);
  11. tmp.free;
  12.  

Winni

PS.:
Demo with Spline Filter added
« Last Edit: April 17, 2021, 07:05:42 pm by winni »

del

  • Full Member
  • ***
  • Posts: 200
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #4 on: April 18, 2021, 06:46:54 am »
That's a cool idea. However, I wonder about the utility of a test image that's smaller than most interpolating kernels. The image will probably get mirror-padded, so that's not a problem. But the higher-order (bigger footprint) kernels give a better truncated approximation of the sinc function, the ideal interpolator. Maybe I'm overthinking this. I'll run the experiment. The higher-order interpolators do give better approximations of the original analog signal. That's pretty much a given.

Thaddy

  • Hero Member
  • *****
  • Posts: 10786
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #5 on: April 18, 2021, 09:26:07 am »
Yes, in the case of images that is true, OTOH with audio it depends.

del

  • Full Member
  • ***
  • Posts: 200
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #6 on: April 20, 2021, 01:58:28 am »
Yeah I guess the real answer is it depends on the image. I don't like blurring and I don't like ringing. But it's a tradeoff. The rfSpline seems to be identical this implementation I have of the Catmull Rom. The input image was a 88x31 "geocities" button. Magnification 1.5 (1 1/2). Then I zoomed in 8x (800%) and took screenshots.

Edit: FWIW here is the procedure that generates the weights for the Catmull Rom kernel:

Code: Pascal  [Select][+][-]
  1. procedure GetCatrom(var catrom: array2flt; i_f: single; j_f: single);
  2. var
  3.   x1, x2, x3, y1, y2, y3, wx, wy, dx, dy: single;
  4.   i, j: integer;
  5.  
  6. begin
  7.   dx := j_f - Trunc(j_f);
  8.   dy := i_f - Trunc(i_f);
  9.  
  10.   for i := 0 to 3 do
  11.   begin
  12.     y1 := Abs(i - (1.0 + dy));
  13.     y2 := y1 * y1;
  14.     y3 := y1 * y2;
  15.  
  16.     if (y1 < 1.0) then
  17.     begin
  18.       wy := 1.5 * y3 - 2.5 * y2 + 1.0
  19.     end
  20.     else if ((y1 >= 1.0) and (y1 <= 2.0)) then
  21.     begin
  22.       wy := -0.5 * y3 + 2.5 * y2 - 4.0 * y1 + 2.0
  23.     end
  24.     else
  25.     begin
  26.       wy := 0.0
  27.     end;
  28.  
  29.     for j := 0 to 3 do
  30.     begin
  31.       x1 := Abs(j - (1.0 + dx));
  32.       x2 := x1 * x1;
  33.       x3 := x1 * x2;
  34.  
  35.       if (x1 < 1.0) then
  36.       begin
  37.         wx := 1.5 * x3 - 2.5 * x2 + 1.0
  38.       end
  39.       else if ((x1 >= 1.0) and (x1 <= 2.0)) then
  40.       begin
  41.         wx := -0.5 * x3 + 2.5 * x2 - 4.0 * x1 + 2.0
  42.       end
  43.       else
  44.       begin
  45.         wx := 0.0
  46.       end;
  47.  
  48.       catrom[i][j] := wx * wy;
  49.     end;
  50.   end;
  51. end;
  52.  
« Last Edit: April 20, 2021, 02:19:39 am by del »

circular

  • Hero Member
  • *****
  • Posts: 3712
    • Personal webpage
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #7 on: April 20, 2021, 08:01:02 pm »
If you're interested you can look in BGRAResample unit how the kernels are computed.

The function WideKernelResample will compute with any kernel you provide.

The rfSpline filter kernel is defined as follows:
Code: Pascal  [Select][+][-]
  1. function TSplineKernel.Interpolation(t: single): single;
  2. var
  3.   tt, ttt: single;
  4. begin
  5.   t := Abs(t);
  6.   tt := Sqr(t);
  7.   ttt := tt * t;
  8.   if t < 1 then
  9.     Result := (2 - Coeff) * ttt - (3 - Coeff) * tt + 1
  10.   else if t < 2 then
  11.     Result := -Coeff * (ttt - 5 * tt + 8 * t - 4)
  12.   else
  13.     Result := 0;
  14. end;
  15.  
  16. function TSplineKernel.KernelWidth: single;
  17. begin
  18.   Result := 2;
  19. end;
Conscience is the debugger of the mind

del

  • Full Member
  • ***
  • Posts: 200
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #8 on: April 21, 2021, 02:48:25 am »
Cool. I'm seeing a pattern here. I pulled some old code off of a backup CD and I had this thing called "PCC". It looks like the Catmull Rom and rfSpline are specific forms of the generic "PCC". I don't remember what "PCC" stood for. "Parametric" Cubic Convolution? "Piece-wise" Cubic Convolution? To make this a Catmull Rom, set "a" (or "Coeff") to -0.5. I notice with "a" set to -0.1 it runs a little "cooler" (less ringing) than the Catmull Rom ("a" = -0.5). Pardon the C++. It was originally the nasty C I used to code in.
Code: C  [Select][+][-]
  1. void GetPCC(Dbl2D& pcc, double x, double y)
  2. {
  3.   double dx {x - floor(x)};
  4.   double dy {y - floor(y)};
  5.   double a {-0.1};
  6.  
  7.   for (int i {0}; i < 4; i++)
  8.   {
  9.     double y1 {fabs(i - (1.0 + dy))};
  10.     double y2 {y1 * y1};
  11.     double y3 {y1 * y2};
  12.     double wy;
  13.  
  14.     if (y1 < 1.0)
  15.     {
  16.       wy = (a + 2.0) * y3 - (a + 3.0) * y2 + 1.0;
  17.     }
  18.     else if ((y1 >= 1.0) && (y1 <= 2.0))
  19.     {
  20.       wy = a * y3 - 5.0 * a * y2 + 8.0 * a * y1 - 4.0 * a;
  21.     }
  22.     else
  23.     {
  24.       wy = 0.0;
  25.     }
  26.  
  27.     for (int j {0}; j < 4; j++)
  28.     {
  29.       double x1 {fabs(j - (1.0 + dx))};
  30.       double x2 {x1 * x1};
  31.       double x3 {x1 * x2};
  32.       double wx;
  33.  
  34.       if (x1 < 1.0)
  35.       {
  36.         wx = (a + 2.0) * x3 - (a + 3.0) * x2 + 1.0;
  37.       }
  38.       else if ((x1 >= 1.0) && (x1 <= 2.0))
  39.       {
  40.         wx = a * x3 - 5.0 * a * x2 + 8.0 * a * x1 - 4.0 * a;
  41.       }
  42.       else
  43.       {
  44.         wx = 0.0;
  45.       }
  46.  
  47.       pcc.m_D2D[i][j] = wx * wy;
  48.     }
  49.   }
  50. }
  51.  
« Last Edit: April 21, 2021, 02:52:02 am by del »

circular

  • Hero Member
  • *****
  • Posts: 3712
    • Personal webpage
Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #9 on: April 21, 2021, 08:41:09 pm »
Yes, your previous formula corresponds to a = -0.5

rfSpline uses Coeff = 0.5. That's just the opposite but the formula is the same (a = -Coeff)
Conscience is the debugger of the mind

del

  • Full Member
  • ***
  • Posts: 200
[SOLVED] Re: TResampleFilter rfBestQuality (BGRABitmapTypes)
« Reply #10 on: April 21, 2021, 09:48:26 pm »
Very cool. I read somewhere that the "Catmull Rom" coefficient (0.5) makes the interpolator continuous in the first derivative. Which is supposed to make it smoother or something. So I really didn't need to code it up, it was already there in rfSpline. I'm gonna mark this thread as "solved". Thanks for all the input.
« Last Edit: April 21, 2021, 09:53:05 pm by del »

 

TinyPortal © 2005-2018