All pastes #11708 Raw Edit

Something

public text v1 · immutable
#11708 ·published 2005-05-13 23:40 UTC
rendered paste body
// methods to extract ready filtered pixels from bitmap in clamped or repeated style

procedure getPixel32_bilinear_clamp(aDib : TosaCustomDIB; x, y : Single; var result : TosaRGB32);
var
  f0, f1, f2, f3 : Single;
  ix, iy, iy2 : Integer;
  fx, fy : Single;
  sc1, sc2 : posaScanline32;
  rc : TosaRGB32;
  c1, c2, c3, c4 : TosaRGB32;
begin
  // extract fractional and int
  fx := Frac(y);
  fy := Frac(x);
  ix := Trunc(x);
  iy := Trunc(y);

  // calculate weights
  f0 := (1-fx) * (1-fy);
  f1 := (1-fx) * fy;
  f2 := fx * fy;
  f3 := fx * (1-fy);

  // default "background" color
  rc := oclWhite;

  if ix >= aDib.Width - 1 then
    begin
      if ix < aDib.Width then
        begin
          // pixel is on / very near egde

          iy2 := iy+1;
          Wrap(iy, aDib.Height-1);
          Wrap(iy2, aDib.Height-1);

          sc1 := aDib.Scanline[iy];
          sc2 := aDib.Scanline[iy2];

          result.r := Round(f0 * sc1[ix].r + f1 * rc.r + f2 * rc.r + f3 * sc2[ix].r);
          result.g := Round(f0 * sc1[ix].g + f1 * rc.g + f2 * rc.g + f3 * sc2[ix].g);
          result.b := Round(f0 * sc1[ix].b + f1 * rc.b + f2 * rc.b + f3 * sc2[ix].b);

          exit;
        end
      else
        begin
          // pixel is outside egde
          result := oclWhite;
          exit;
        end;
    end
  else if ix < 0 then
    begin
      if ix+1 = 0 then
        begin
          iy2 := iy+1;
          Wrap(iy, aDib.Height-1);
          Wrap(iy2, aDib.Height-1);

          sc1 := aDib.Scanline[iy];
          sc2 := aDib.Scanline[iy2];

          rc := oclWhite;

          result.r := Round(f0 * sc1[ix+1].r + f1 * rc.r + f2 * rc.r + f3 * sc2[ix+1].r);
          result.g := Round(f0 * sc1[ix+1].g + f1 * rc.g + f2 * rc.g + f3 * sc2[ix+1].g);
          result.b := Round(f0 * sc1[ix+1].b + f1 * rc.b + f2 * rc.b + f3 * sc2[ix+1].b);

          exit;
        end;
      result := oclWhite;
      exit;
    end
  else if iy > aDib.Height - 2 then
    begin
      if iy < aDib.Height then
        begin
          sc1 := aDib.Scanline[iy];
          result.r := Round(f0 * sc1[ix].r + f1 * sc1[ix+1].r + f2 * rc.r + f3 * rc.r);
          result.g := Round(f0 * sc1[ix].g + f1 * sc1[ix+1].g + f2 * rc.g + f3 * rc.g);
          result.b := Round(f0 * sc1[ix].b + f1 * sc1[ix+1].b + f2 * rc.b + f3 * rc.b);
          exit;
        end;

      result := oclWhite;
      exit;
    end
  else if iy < 0 then
    begin
      if iy + 1 = 0 then
        begin
          rc := oclWhite;
          sc1 := aDib.Scanline[0];

          c1 := rc;
          c2 := rc;
          c3 := sc1[ix+1];
          c4 := sc1[ix];
          result.r := Round(f0 * c1.r + f1 * c2.r + f2 * c3.r + f3 * c4.r);
          result.g := Round(f0 * c1.g + f1 * c2.g + f2 * c3.g + f3 * c4.g);
          result.b := Round(f0 * c1.b + f1 * c2.b + f2 * c3.b + f3 * c4.b);
          exit;
        end;
      result := oclWhite;
      exit;
    end;

  // wrap iy2 based on iy's relation to height
  if iy + 1 > aDib.Height - 1 then iy2 := 0 else iy2 := iy + 1;

  // setup scanlinepointers
  sc1 := aDib.Scanline[iy];
  sc2 := aDib.Scanline[iy2];

  // calculated interpolated
  result.r := Round(f0 * sc1[ix].r + f1 * sc1[ix+1].r + f2 * sc2[ix+1].r + f3 * sc2[ix].r);
  result.g := Round(f0 * sc1[ix].g + f1 * sc1[ix+1].g + f2 * sc2[ix+1].g + f3 * sc2[ix].g);
  result.b := Round(f0 * sc1[ix].b + f1 * sc1[ix+1].b + f2 * sc2[ix+1].b + f3 * sc2[ix].b);
end;

procedure getPixel32_bilinear_wrap(aDib : TosaCustomDIB; x, y : Single; var result : TosaRGB32);
var
  f0, f1, f2, f3 : Single;
  ix, iy : Integer;
  ix2, iy2 : Integer;
  fx, fy : Single;
  sc1, sc2 : posaScanline32;
begin
  // THIS METHOD HAS BEEN OPTMIZED FOR AND THEREFOR
  // VARIABLES MAY NOT CONTAIN THE VALUE INTENDED TO
  // AT ANY TIME. SEPARATION OF BLOCKS MEANS A LOT

  // in the wrap x/y section temp was replaced with the intvar iy

  // wrap X coordinates
  iy := aDib.Width-1;
  if x > iy then
    while x > iy do
      x := x - iy
  else if x < 0 then
    while x < 0 do
      x := x + iy;

  // wrap Y coordinates
  iy := aDib.Height-1;
  if y > iy then
    while y > iy do
      y := y - iy
  else if y < 0 then
    while y < 0 do
      y := y + iy;

  // extract fractional and int
  fx := Frac(y);
  fy := Frac(x);
  
  ix := trunc(x);
  iy := trunc(y);

  // wrap the interpolator contribotur coordinates
  // OPT : Tried to optmize for branch prediction failure
  iy2 := iy+1;
  if iy+1 > aDib.Height - 1 then iy2 := 0;

  ix2 := ix+1;
  if ix+1 > aDib.Width - 1 then ix2 := 0;

  // calulate weights
  f0 := (1-fx) * (1-fy);
  f3 := fx * (1-fy);
  f1 := (1-fx) * fy;
  f2 := fx * fy;

  // setup scanlinepointers
  sc1 := aDib.Scanline[iy];
  sc2 := aDib.Scanline[iy2];

  // calculated interpolated pixelsums
  result.r := Round(f0 * sc1[ix].r + f1 * sc1[ix2].r + f2 * sc2[ix2].r + f3 * sc2[ix].r);
  result.g := Round(f0 * sc1[ix].g + f1 * sc1[ix2].g + f2 * sc2[ix2].g + f3 * sc2[ix].g);
  result.b := Round(f0 * sc1[ix].b + f1 * sc1[ix2].b + f2 * sc2[ix2].b + f3 * sc2[ix].b);
end;