1. 程式人生 > >一種完美的降取樣插值方法

一種完美的降取樣插值方法

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; }