一種完美的降取樣插值方法
阿新 • • 發佈:2019-02-11
1,本文以RGBA 圖片的降取樣為例子
2, 先縱向插值
3,然後橫向插值
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
//縱向差值
/* src 輸入圖片資料指標
des 輸出圖片的資料指標
srcW 輸入圖片的寬
srcH 輸入圖片的高
desH 輸出圖片的高 */
int BilinearInterpolationCol(unsigned char * src, unsigned char * des, int srcW, int srcH, int desH)
{
float scale = (float)desH / (float)srcH;
float invscale = (float)srcH / (float)desH;
int i, j, z;
float fsy1;
float fsy2;
int sy1;
int sy2;
int k = 0;
int m = 0;
int skip = (int)(ceil(invscale) + 1.0f);
float * weight = (float *)malloc (skip * sizeof(float));
int * srcIndex = (int *)malloc(skip * sizeof(int));
for(i = 0; i < desH; i ++)
{
int temp[3];
memset(weight, 0, sizeof(float) * skip);
memset(srcIndex, 0, sizeof(int) * skip);
k = 0;
m = 0;
fsy1 = (float) i * invscale;
fsy2 = fsy1 + invscale;
sy1 = (int )ceil(fsy1);
sy2 = (int)floor(fsy2);
if((float)sy1 - fsy1 > 0.001f)
{
srcIndex[k] = (sy1 - 1);
weight[k] = ((float)sy1 - fsy1) * scale;
k ++;
}
for(m = sy1; m < sy2; m ++)
{
srcIndex[k] = m;
weight[k] = scale;
k ++;
}
if(fsy2 - (float)(sy2) > 0.001f)
{
srcIndex[k] = sy2;
weight[k] = (fsy2 - (float)(sy2)) * scale;
k ++;
}
for(j = 0; j < srcW; j ++)
{
float tempFloat[3] = {0.0f, 0.0f, 0.0f};
for(z = 0; z < skip; z ++)
{
srcIndex[z] = min(srcIndex[z], (srcH - 1));
tempFloat[0] += ((int)src[(srcIndex[z] * srcW + j) * 4 + 0]) * weight[z];
tempFloat[1] += ((int)src[(srcIndex[z] * srcW + j) * 4 + 1]) * weight[z];
tempFloat[2] += ((int)src[(srcIndex[z] * srcW + j) * 4 + 2]) * weight[z];
}
temp[0] = (int)tempFloat[0];
temp[1] = (int)tempFloat[1];
temp[2] = (int)tempFloat[2];
des[(i * srcW + j) * 4 + 0] = (unsigned char)temp[0];
des[(i * srcW + j) * 4 + 1] = (unsigned char)temp[1];
des[(i * srcW + j) * 4 + 2] = (unsigned char)temp[2];
des[(i * srcW + j) * 4 + 3] = 0;
}
}
free(weight);
free(srcIndex);
return 0;
}
/* 橫向插值
src 輸入圖片資料指標
des 輸出圖片的資料指標
srcW 輸入圖片的寬
srcH 輸入圖片的高
desW 輸出圖片的寬 */
int BilinearInterpolationRow(unsigned char * src, unsigned char * des, int srcW, int srcH, int desW)
{
float scale = (float)desW / (float)srcW;
float invscale = (float)srcW / (float)desW;
int i, j, z;
float fsx1;
float fsx2;
int sx1;
int sx2;
int k = 0;
int m = 0;
int skip = (int)(ceil(invscale) + 1.0f);
float * weight = (float *)malloc(skip * sizeof(float));
int * srcIndex = (int *)malloc(skip * sizeof(int));
for(j = 0; j < desW; j ++)
{
int temp[3];
memset(weight, 0, sizeof(float) * skip);
memset(srcIndex, 0, sizeof(int) * skip);
k = 0;
m = 0;
fsx1 = (float) j * invscale;
fsx2 = fsx1 + invscale;
sx1 = (int)ceil(fsx1);
sx2 = (int)floor(fsx2);
if((float)sx1 - fsx1 > 0.001f)
{
srcIndex[k] = (sx1 - 1);
weight[k] = ((float)sx1 - fsx1) * scale;
k ++;
}
for(m = sx1; m < sx2; m ++)
{
srcIndex[k] = m;
weight[k] = scale;
k ++;
}
if(fsx2 - (float)(sx2) > 0.001f)
{
srcIndex[k] = sx2;
weight[k] = (fsx2 - (float)(sx2)) * scale;
k ++;
}
for(i = 0; i < srcH; i ++)
{
float tempFloat[3] = {0.0f, 0.0f, 0.0f};
for(z = 0; z < skip; z ++)
{
srcIndex[z] = min(srcIndex[z], (srcW -1));
tempFloat[0] += ((int)src[(i * srcW + srcIndex[z]) * 4 + 0]) * weight[z];
tempFloat[1] += ((int)src[(i * srcW + srcIndex[z]) * 4 + 1]) * weight[z];
tempFloat[2] += ((int)src[(i * srcW + srcIndex[z]) * 4 + 2]) * weight[z];
}
temp[0] = (int)tempFloat[0];
temp[1] = (int)tempFloat[1];
temp[2] = (int)tempFloat[2];
des[(i * desW + j) * 4 + 0] = (unsigned char)temp[0];
des[(i * desW + j) * 4 + 1] = (unsigned char)temp[1];
des[(i * desW + j) * 4 + 2] = (unsigned char)temp[2];
des[(i * desW + j) * 4 + 3] = 0;
}
}
free(weight);
free(srcIndex);
return 0;
}
/* 對外提供的介面
RGBA 影象降取樣的差值方法
src 輸入圖片資料指標
des 輸出圖片的資料指標
srcW 輸入圖片的寬
srcW 輸出圖片寬
srcH 輸入圖片的高
*/
int ImageResize(unsigned char * src, unsigned char * des, int srcW, int srcH, int desW, int desH)
{
// 縱向差值
unsigned char * temp = (unsigned char *)malloc(srcW * desH * sizeof(char) * 4);
BilinearInterpolationCol(src, temp, srcW, srcH, desH);
//橫向差值
BilinearInterpolationRow(temp, des, srcW, desH, desW);
free(temp);
return 0;
}