Double cubic interpolation of image scaling
One: Mathematical Principles
If you know a function f (x) and its derivative at x=0,x=1, then the function can be interpolated between [0,1], when the function
When expressed as a three-time polynomial, we call the cubic interpolation. A three-time polynomial and its derivative:
F (x) =ax^3 +bx^2 + cx + D
F ' (x) =3ax^2 + 2bx +c
The polynomial at x=0, the X=1 value and its derivative values are:
F (0) = D;
F (1) = a + B + C + D;
F ' (0) =c
F ' (1) =3a + 2b + C
The above four equations can be equivalent to the following transformations:
A= 2f (0) –2f (1) + F ' (0) + F ' (1)
b= -3f (0) + 3f (1) –2f ' (0) –f ' (1)
c= F ' (0)
D= f ' (1)
Suppose you have four point values P0, p1, p2, p3 respectively in X=-1, X=0, X=1, x=2, assign values to f (0), F (1), F ' (0), respectively,
F ' (1) is:
F (0) = P1
F (1) = P2
F ' (0) = (p2–p0)/2
F ' (1) = (P3-P1)/2
This our cubic interpolation formula becomes:
F (p0,p1,p2,p3, X) = ( -1/2p0 + 3/2p1-3/2p2+ 1/2p3) X^3 + (p0-5/2p1 + 2p2-1/2d) x^2 + ( -1/2p0 +
1/2P2) x + p1
The two-cubic interpolation is the expression of cubic interpolation in two-dimensional space, and the interpolation formula can be expressed as:
G (x, y) = f (f (p00, P01, P02, p03, y), F (p10,p11, P12, P13, y), F (P20, P21, P22, P23, y), F (P30, p31, P32, P33, y), X)
The value of a g (x, y) target interpolation point can be obtained by solving the 16 parameters.
Two: Dual-cubic interpolation advantages and disadvantages
Double-cubic interpolation in the image amplification process can retain more image details, enlarge the image with anti-aliasing after the function,
At the same time, the effect of image and source image is more real, the disadvantage is that the computational volume is relatively large, is a common three kinds of image amplification algorithm
One of the largest computational weights, it is said that Photoshop image amplification is the basic two-cubic interpolation optimization algorithm
Third: The operation effect of the program is as follows:
Four: Critical code resolution
Do not want to explain too much, the most important thing is to calculate the number of floating-point coordinates of the decimal part, that is, X, y range of values between [0,1]
V: Java-based program complete source code
public class Bicubicinterpolationscale implements Imagescale {private double a00, A01, A02, A03;
Private double A10, A11, A12, A13;
Private double A20, A21, A22, A23;
Private double A30, A31, A32, A33;
private int srcwidth;
private int srcheight; @Override public int[] Imgscale (int[] inpixelsdata, int srcw, int srcH, int destw, int desth) {double[][][] Input3ddat
A = Processonetothreedeminsion (Inpixelsdata, SrcH, SRCW);
int[][][] Outputthreedeminsiondata = new Int[desth][destw][4];
double[][] Temppixels = new Double[4][4];
float Rowratio = ((float) SrcH)/((float) desth);
float Colratio = ((float) SRCW)/((float) DESTW);
This.srcwidth = SRCW;
This.srcheight = SrcH;
for (int row=0; row<desth; row++) {//Convert to three dimension data double Srcrow = ((float) row) *rowratio;
Double J = Math.floor (Srcrow);
Double T = srcrow-j;
for (int col=0; col<destw; col++) {Double srccol = ((float) col) *colratio;
Double k = Math.floor (Srccol); Double u = srccol-k;
for (int i=0; i<4; i++) {temppixels[0][0] = Getrgbvalue (input3ddata,j-1, k-1,i);
TEMPPIXELS[0][1] = Getrgbvalue (input3ddata,j-1, k, i);
TEMPPIXELS[0][2] = Getrgbvalue (Input3ddata, j-1,k+1, i);
TEMPPIXELS[0][3] = Getrgbvalue (Input3ddata, j-1, k+2,i);
Temppixels[1][0] = Getrgbvalue (Input3ddata, J, K-1, I);
TEMPPIXELS[1][1] = Getrgbvalue (Input3ddata, J, K, I);
TEMPPIXELS[1][2] = Getrgbvalue (Input3ddata, J, k+1, I);
TEMPPIXELS[1][3] = Getrgbvalue (Input3ddata, J, k+2, I);
Temppixels[2][0] = Getrgbvalue (Input3ddata, j+1,k-1,i);
TEMPPIXELS[2][1] = Getrgbvalue (Input3ddata, j+1, K, i);
TEMPPIXELS[2][2] = Getrgbvalue (Input3ddata, j+1, k+1, i);
TEMPPIXELS[2][3] = Getrgbvalue (Input3ddata, j+1, k+2, i);
Temppixels[3][0] = Getrgbvalue (Input3ddata, j+2, k-1, i);
TEMPPIXELS[3][1] = Getrgbvalue (Input3ddata, j+2, K, i);
TEMPPIXELS[3][2] = Getrgbvalue (Input3ddata, j+2, k+1, i); TemPPIXELS[3][3] = Getrgbvalue (Input3ddata, j+2, k+2, i);
Update coefficients updatecoefficients (temppixels);
Outputthreedeminsiondata[row][col][i] = Getpixelvalue (GetValue (T, u));
}} return Converttoonedim (Outputthreedeminsiondata, DESTW, desth);
Public double Getrgbvalue (double[][][] input3ddata, double row, double col, int index) {if (Col >= srcwidth) {
col = srcWidth-1;
} if (Col < 0) {col = 0;
} if (row >= srcheight) {row = srcHeight-1;
} if (Row < 0) {row = 0;
return input3ddata[(int) row][(int) col][index]; public int Getpixelvalue (double pixelvalue) {return Pixelvalue < 0? 0:pixelvalue >255.0d? 255: (int) Pixelva
Lue
} public void Updatecoefficients (double[][] p) {a00 = p[1][1];
A01 =-.5*p[1][0] +. 5*p[1][2];
A02 = p[1][0]-2.5*p[1][1] + 2*p[1][2]-. 5*p[1][3];
A03 =-.5*p[1][0] + 1.5*p[1][1]-1.5*p[1][2] +. 5*p[1][3]; A10 =-.5*p[0][1] +. 5*p[2][1];
A11 =. 25*p[0][0]-. 25*p[0][2]-. 25*p[2][0] +. 25*p[2][2];
A12 =-.5*p[0][0] + 1.25*p[0][1]-p[0][2] +. 25*p[0][3] +. 5*p[2][0]-1.25*p[2][1] + p[2][2]-. 25*p[2][3];
A13 =. 25*p[0][0]-. 75*p[0][1] +. 75*p[0][2]-. 25*p[0][3]-. 25*p[2][0] +. 75*p[2][1]-. 75*p[2][2] +. 25*p[2][3];
A20 = p[0][1]-2.5*p[1][1] + 2*p[2][1]-. 5*p[3][1];
A21 =-.5*p[0][0] +. 5*p[0][2] + 1.25*p[1][0]-1.25*p[1][2]-p[2][0] + p[2][2] +. 25*p[3][0]-. 25*p[3][2]; A22 = p[0][0]-2.5*p[0][1] + 2*p[0][2]-. 5*p[0][3]-2.5*p[1][0] + 6.25*p[1][1]-5*p[1][2] + 1.25*p[1][3] + 2*p[2][0]-
5*P[2][1] + 4*p[2][2]-p[2][3]-. 5*p[3][0] + 1.25*p[3][1]-p[3][2] +. 25*p[3][3]; A23 =-.5*p[0][0] + 1.5*p[0][1]-1.5*p[0][2] +. 5*p[0][3] + 1.25*p[1][0]-3.75*p[1][1] + 3.75*p[1][2]-1.25*p[1][3]-P [2]
[0] + 3*p[2][1]-3*p[2][2] + p[2][3] +. 25*p[3][0]-. 75*p[3][1] +. 75*p[3][2]-. 25*p[3][3];
A30 =-.5*p[0][1] + 1.5*p[1][1]-1.5*p[2][1] +. 5*p[3][1]; A31 =. 25*p[0][0]-. 25*p[0][2]-. 75*p[1][0] +. 75*p[1][2] +. 75*p[2][0]-. 75*p[2][2]-. 25*p[3][0] +. 25*p[3][2]; A32 =-.5*p[0][0] + 1.25*p[0][1]-p[0][2] +. 25*p[0][3] + 1.5*p[1][0]-3.75*p[1][1] + 3*p[1][2]-. 75*p[1][3]-1.5*p[2]
[0] + 3.75*p[2][1]-3*p[2][2] +. 75*p[2][3] +. 5*p[3][0]-1.25*p[3][1] + p[3][2]-. 25*p[3][3]; A33 =. 25*p[0][0]-. 75*p[0][1] +. 75*p[0][2]-. 25*p[0][3]-. 75*p[1][0] + 2.25*p[1][1]-2.25*p[1][2] +. 75*p[1][3] +. 7
5*P[2][0]-2.25*p[2][1] + 2.25*p[2][2]-. 75*p[2][3]-. 25*p[3][0] +. 75*p[3][1]-. 75*p[3][2] +. 25*p[3][3];
Public double GetValue (double x, double y) {double x2 = x * x;
Double x3 = x2 * x;
Double y2 = y * y;
Double y3 = y2 * y; Return (A00 + A01 * y + a02 * y2 + a03 * y3) + (A10 + A11 * y + A12 * y2 + A13 * y3) * x + (a20 + A21 *
Y + A22 * y2 + A23 * y3) * x2 + (A30 + a31 * y + a32 * y2 + a33 * y3) * x3;
}/* <p> The purpose ' this ' is ' to convert ' data in ' 3D array of ints back into </p>* <p> 1d array of type int. </p> * */public int[] Converttoonedim (int[][][] data, int imgcols, int Imgrows) {//Create the 1D array of type int to is populated with pixel data int[] Onedpix = new Int[imgcols * Imgrow
S * 4]; Move the data into the 1D array. Note the//with the bitwise OR operator and the//bitwise LEFT-SHIFT operators to put the//four 8-bit bytes in
to each int. for (int row = 0, cnt = 0; row < imgrows; row++) {for (int col = 0; col < imgcols; col++) {onedpix[cnt] = ( (Data[row][col][0] <<) & 0xff000000 | ((Data[row][col][1] <<) & 0x00ff0000 | ((Data[row][col][2] << 8) & 0X0000FF00 |
((Data[row][col][3]) & 0X000000FF);
cnt++;
}//end to Loop on Col}//end for loop on row return Onedpix;
}//end Converttoonedim Private double [][][] Processonetothreedeminsion (int[] oneDPix2, int imgrows, int imgcols) { double[][][] TempData = newDOUBLE[IMGROWS][IMGCOLS][4];
for (int row=0; row>) & 0xFF; Alpha Tempdata[row][col][1] = (Arow[col] >>) & 0xFF; Red tempdata[row][col][2] = (Arow[col] >> 8) & 0xFF; Green tempdata[row][col][3] = (Arow[col]) & 0xFF;
Blue} return tempdata; }
}
VI: The end
This three article is about the fundamentals, methods, and implementations of image scaling, if you want to get all the source code
Can contact me. If there are any errors in the article, please note.