画像処理入門 > 拡大縮小 > バイキュービック

バイキュービック


バイキュービック
バイキュービックのプログラムです。
画像の端の処理は未実装です。
速度、簡潔さなど度外視で、とりあえず実装した版です。

サンプルプログラム
プログラムはこちら #define KEISU_A -1.0 double calcH(double inValue, double aValue){ double tmpValue = abs(inValue); double outValue; if(tmpValue <= 1){ outValue = (aValue + 2.0) * tmpValue * tmpValue * tmpValue - (aValue + 3.0) * tmpValue * tmpValue + 1.0; } else if(tmpValue <= 2){ outValue = aValue * tmpValue * tmpValue * tmpValue - 5 * aValue * tmpValue * tmpValue + 8.0 * aValue * tmpValue - 4.0 * aValue; } else { outValue = 0.0; } return outValue; } double calcH(double inValue){ double outValue = calcH(inValue, -1.0); return outValue; } /* in : 横は4バイト */ void Bicubic(unsigned char *out, unsigned char *in, int inHeight, int inWidth, int inChannel, double mag){ int height; int width; int outStep; int inStep; int i, j; double inX, inY; double inXa[4], inYa[4]; double hx[4], hy[4]; int indexY[4]; int indexX[4]; double tmp; height = (int)((double)inHeight * mag); width = (int)((double)inWidth * mag); // OpenCVで使用する画像データの横幅は4バイト区切りのため調整 inStep = inWidth * inChannel; if( (inStep % 4) != 0){ inStep = inStep + (4 - inStep %4); } outStep = width * inChannel; if( (outStep % 4) != 0){ outStep = outStep + (4 - outStep %4); } // ループ中にif文を書くと遅いためループ前にビット数の条件分岐 switch(inChannel){ case 1: // 8bit画像 for(i = 0; i < height; ++i){ inY = (double)i / mag; // 入力画像の高さを超えないようにする if((int)inY >= inHeight - 1){ --inY; } inYa[0] = 1 + inY - (int)inY; inYa[1] = inY - (int)inY; inYa[2] = (int)inY + 1 - inY; inYa[3] = (int)inY + 2 - inY; inYa[0] = calcH(inYa[0], KEISU_A); inYa[1] = calcH(inYa[1], KEISU_A); inYa[2] = calcH(inYa[2], KEISU_A); inYa[3] = calcH(inYa[3], KEISU_A); if(inYa[0] < 0 && inYa[0] > -0.001){ inYa[0] = 0.0; } if(inYa[1] < 0 && inYa[1] > -0.001){ inYa[1] = 0.0; } if(inYa[2] < 0 && inYa[2] > -0.001){ inYa[2] = 0.0; } if(inYa[3] < 0 && inYa[3] > -0.001){ inYa[3] = 0.0; } if(inYa[0] > 1.0){ inYa[0] = 1.0; } if(inYa[1] > 1.0){ inYa[1] = 1.0; } if(inYa[2] > 1.0){ inYa[2] = 1.0; } if(inYa[3] > 1.0){ inYa[3] = 1.0; } if(inY >= 1.0){ indexY[0] = ((int)inY - 1) * inStep; } else { indexY[0] = (int)inY * inStep; } indexY[1] = (int)inY * inStep; indexY[2] = ((int)inY + 1) * inStep; indexY[3] = ((int)inY + 2) * inStep; for(j = 0; j < width; ++j){ // 入力画像の幅を超えないようにする inX = (double)j / mag; if((int)inX >= inWidth - 1){ --inX; } inXa[0] = 1 + inX - (int)inX; inXa[1] = inX - (int)inX; inXa[2] = (int)inX + 1 - inX; inXa[3] = (int)inX + 2 - inX; inXa[0] = calcH(inXa[0], KEISU_A); inXa[1] = calcH(inXa[1], KEISU_A); inXa[2] = calcH(inXa[2], KEISU_A); inXa[3] = calcH(inXa[3], KEISU_A); if(inXa[0] < 0 && inXa[0] > -0.001){ inXa[0] = 0.0; } if(inXa[1] < 0 && inXa[1] > -0.001){ inXa[1] = 0.0; } if(inXa[2] < 0 && inXa[2] > -0.001){ inXa[2] = 0.0; } if(inXa[3] < 0 && inXa[3] > -0.001){ inXa[3] = 0.0; } if(inXa[0] > 1.0){ inXa[0] = 1.0; } if(inXa[1] > 1.0){ inXa[1] = 1.0; } if(inXa[2] > 1.0){ inXa[2] = 1.0; } if(inXa[3] > 1.0){ inXa[3] = 1.0; } if(inX >= 1.0){ indexX[0] = (int)(inX - 1) * inChannel; } else { indexX[0] = (int)inX * inChannel; } indexX[1] = (int)inX * inChannel; indexX[2] = (int)(inX + 1) * inChannel; indexX[3] = (int)(inX + 2) * inChannel; tmp = (inYa[0] * (inXa[0] * in[indexY[0] + indexX[0]] + inXa[1] * in[indexY[0] +indexX[1]] + inXa[2] * in[indexY[0] +indexX[2]] + inXa[3] * in[indexY[0] +indexX[3]]) + inYa[1] * (inXa[0] * in[indexY[1] + indexX[0]] + inXa[1] * in[indexY[1] +indexX[1]] + inXa[2] * in[indexY[1] +indexX[2]] + inXa[3] * in[indexY[1] +indexX[3]]) + inYa[2] * (inXa[0] * in[indexY[2] + indexX[0]] + inXa[1] * in[indexY[2] +indexX[1]] + inXa[2] * in[indexY[2] +indexX[2]] + inXa[3] * in[indexY[2] +indexX[3]]) + inYa[3] * (inXa[0] * in[indexY[3] + indexX[0]] + inXa[1] * in[indexY[3] +indexX[1]] + inXa[2] * in[indexY[3] +indexX[2]] + inXa[3] * in[indexY[3] +indexX[3]])); if(tmp > 255.0){ tmp = 255; } else if(tmp < 0.0){ tmp = 0; } out[i * outStep + j] = tmp; } } break; case 3: break; case 4: // 32bit画像 break; default: break; } }