我有一个在互联网上找到的用于调整图像大小的代码,但是有一个问题。我的宽度和高度偏移量为-1px。
我尝试添加该偏移量,但是它只是擦除了第一行,然后删除了1 px。
private byte[] BicubicResize(byte[] Data, int w, int h, double scalex, double scaley)
{
int w_new = (int)(w * scalex);
int h_new = (int)(h * scaley);
byte[] NewData = new byte[w_new * h_new * 4];
byte c;
int x, y;
BicubicInterpolation interpolation = new BicubicInterpolation(scalex, scaley, w_new, h_new);
for (c = 0; c < 4; c++)
for (y = 0; y < h_new; y++)
for (x = 0; x < w_new; x++)
NewData[((x + y * w_new) << 2) | c] = interpolation.Bicubic(x, y, c, Data);
return NewData;
}
public class BicubicInterpolation
{
double dx;
double dy;
double p0;
double p1;
double p2;
double p3;
double[] Rdx;
double[] Rdy;
double s;
byte k;
byte i;
long pix0;
long pix1;
double[][] p;
double scalex;
double scaley;
int w;
int h;
public BicubicInterpolation(double scalex = 1, double scaley = 1, int w = 0, int h = 0)
{
p = new double[4][];
p[0] = new double[4];
p[1] = new double[4];
p[2] = new double[4];
p[3] = new double[4];
pix0 = 0;
pix1 = 0;
this.scalex = scalex;
this.scaley = scaley;
this.w = w;
this.h = h;
}
public byte Bicubic(int x, int y, byte c, byte[] Data)
{
pix0 = (long)(x / scalex) + (long)(y / scaley) * (long)(w / scalex);
for (k = 0; k < 4; k++)
for (i = 0; i < 4; i++)
{
pix1 = ((long)(pix0 + i + k * (w / scalex)) << 2) | c;
if (pix1 < Data.LongLength) p[i][k] = Data[pix1];
else p[i][k] = 0;
}
//Temp = BicubicInterpolate(p, x - (long)(x / scalex), y - (long)(y / scaley));
return (byte)Interpolation(x, y, p);
}
private double Interpolation(double tx, double ty, double[][] P)
{
dx = F(tx);
dy = F(ty);
Rdx = new double[4];
Rdy = new double[4];
for (int n = 0; n < 4; n++)
{
Rdx[n] = R(n - 1 - dx);
Rdy[n] = R(n - 1 - dy);
}
s = 0;
for (byte k = 0; k < 4; k++)
for (byte i = 0; i < 4; i++)
s += P[k][i] * Rdx[i] * Rdy[k];
return s;
}
private double F(double x) => x - Math.Floor(x);
private double P(double x) => (x > 0.0) ? x : 0.0;
private double R(double x)
{
//return (Math.Pow(P(x + 2), 3) - 4 * Math.Pow(P(x + 1), 3) +
// 6 * Math.Pow(P(x), 3) - 4 * Math.Pow(P(x - 1), 3)) / 6;
p0 = P(x + 2);
p1 = P(x + 1);
p2 = P(x );
p3 = P(x - 1);
return ((p0 * p0 * p0) - 4 * (p1 * p1 * p1) + 6 * (p2 * p2 * p2) - 4 * (p3 * p3 * p3)) / 6.0;
}
}
我期望得到类似这样的东西:Original。
但是我得到的图像在宽度和高度上有问题的偏移-1px:Problem output
答案 0 :(得分:0)
我以其他方式找到了答案。和这种方式是更快。
public byte[,,] BicubicResize(byte[,,] Data, int w, int h, int w_new, int h_new, double scalex, double scaley)
{
byte[,,] NewData = new byte[w_new, h_new, 4];
byte c;
int x, y;
double j, l;
byte k, i;
double[][] p = new double[4][];
p[0] = new double[4];
p[1] = new double[4];
p[2] = new double[4];
p[3] = new double[4];
double result = 0;
for (c = 0; c < 4; c++)
for (y = 0; y < h_new; y++)
for (x = 0; x < w_new; x++)
{
for (k = 0; k < 4; k++)
for (i = 0; i < 4; i++)
{
j = x / scalex + i - 1;
l = y / scaley + k - 1;
while (j < 0) j++;
while (l < 0) l++;
while (j >= w) j--;
while (l >= h) l--;
p[i][k] = Data[(int)j, (int)l, c];
}
result = BicubicInterpolate(p, x % scalex / scalex, y % scaley / scaley);
NewData[x, y, c] = CDTB(result);
}
return NewData;
}
private readonly double[] arr = new double[4];
private double result = 0;
private double BicubicInterpolate(double[][] p, double x, double y)
{
arr[0] = CubicInterpolate(p[0], y);
arr[1] = CubicInterpolate(p[1], y);
arr[2] = CubicInterpolate(p[2], y);
arr[3] = CubicInterpolate(p[3], y);
result = CubicInterpolate(arr, x);
return result;
}
private double CubicInterpolate(double[] p, double x) => p[1] + 0.5 * x * (p[2] - p[0] + x *
(2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
public static byte CDTB(double c)
{
if (c * 10 % 10 > 5) c = Math.Ceiling(c);
else c = Math.Floor (c);
if (c > 0xFF) c = 0xFF;
else if (c < 0x00) c = 0x00;
return (byte)c;
}