2016-10-06 15 views
0

私は大きなサイズ(960x960)から32x32ほどの小さな画像に縮小しようとしています。バッファを使用してイメージを縮小/補間するアルゴリズムですか?

 int width = scale*img->getWidth(); 
     int height = scale*img->getHeight(); 
     Image* scaledImage = new Image(); 
     auto dataLen = width * height * x * sizeof(unsigned char); 
     auto data2 = static_cast<unsigned char*>(malloc(dataLen)); 
     scaledImage->initWithRawData(data2, dataLen, width, height, 8); 

そして、私がやって出力画像の個々のピクセルを設定することができます。私がやって出力画像を作成することができます

Image* img = new Image(); 
    img->initWithImageFile(fileNameWithPath); 
    int x=3; 
    if(img->hasAlpha()){ 
     x=4; 
    } 

    unsigned char *data = new unsigned char[img->getDataLen()*x]; 
    data = img->getData(); 
    // [0][0] => Left-Top Pixel ! 
    // But cocos2d Location Y-axis is Bottom(0) to Top(max) 

    //This is for changing pixels in the original image 
    //Skip this loop if there are no changes to be made (converting to grayscale etc). 
    for(int i=0;i<img->getWidth();i++) 
    { 
     for(int j=0;j<img->getHeight();j++) 
     { 
      unsigned char *pixel = data + (i + j * img->getWidth()) * x; 

      // You can see/change pixels' RGBA value(0-255) here ! 
      unsigned char r = *pixel; 
      unsigned char g = *(pixel + 1); 
      unsigned char b = *(pixel + 2) ; 
      unsigned char a = *(pixel + 3); 

      //pixel[2] = 255; //Example: Setting the blue component to 255 
     } 
    } 

:私は、私は生のピクセルを取得するには、次のコードを使用しています:

  unsigned char *pixel2 = data2 + (i + j * width) * x; 

質問は(必要と少ないメモリ場合、より多くのCPUを使用するように有利に、最小のCPUとメモリを使用して)/平均効率的に原画像から画素​​を補間する方法です。

課題:

  1. ダウンスケール画像と元の画像が 倍数完璧ではないかもしれません。
  2. ダウンスケーリングされたイメージは、元のイメージサイズの の0.1と小さくてもかまいません。
  3. ほとんどの画像は元の画像の0.4〜0.1に縮小されるため、これらが最も重要な範囲です。

EDIT:(バイリニアの代わりに)他の補間アルゴリズムが適していると思えば、私はそれを開いています。課題は、個々のピクセルを平均/補間する効率的なアルゴリズムを書くことです。

元の画像の個々のピクセルをどのように補間しますか?

+0

ここでは特定の質問は表示されません。 – xaxxon

+0

質問は1回のパスで個々のピクセルを補間する方法です... –

+1

この質問は非常によく知られているようです。 – xaxxon

答えて

2

メモリに問題はありません。入力バッファに元のイメージがあり、出力バッファに再スケーリングされたイメージが必要な場合は、もう必要ありません。

双線形補間は、大きな要因によるダウンサンプリングにはあまり適していません。なぜなら、最も近いサンプリングと実際には異なるわけではないからです。隣接する4つのピクセルだけを補間するので、特にコンピュータ生成の画像ではエイリアシングの影響を受け易い。

この関数は、平均化メソッドを使用します。

/* 
    resize an image using the averaging method. 
    Note that dwidth and dheight must be smaller than or equal to swidth, sheight. 

*/ 
void sprshrink(unsigned char *dest, int dwidth, int dheight, unsigned char *src, int swidth, int sheight) 
{ 
    int x, y; 
    int i, ii; 
    float red, green, blue, alpha; 
    float xfrag, yfrag, xfrag2, yfrag2; 
    float xt, yt, dx, dy; 
    int xi, yi; 


    dx = ((float)swidth)/dwidth; 
    dy = ((float)sheight)/dheight; 

    for(yt= 0, y=0;y<dheight;y++, yt += dy) 
    { 
    yfrag = ceil(yt) - yt; 
    if(yfrag == 0) 
     yfrag = 1; 
    yfrag2 = yt+dy - (float) floor(yt + dy); 
    if(yfrag2 == 0 && dy != 1.0f) 
     yfrag2 = 1; 

    for(xt = 0, x=0;x<dwidth;x++, xt+= dx) 
    { 
     xi = (int) xt; 
     yi = (int) yt; 
     xfrag = (float) ceil(xt) - xt; 
    if(xfrag == 0) 
     xfrag = 1; 
     xfrag2 = xt+dx - (float) floor(xt+dx); 
    if(xfrag2 == 0 && dx != 1.0f) 
     xfrag2 = 1; 
     red = xfrag * yfrag * src[(yi*swidth+xi)*4]; 
     green = xfrag * yfrag * src[(yi*swidth+xi)*4+1]; 
     blue = xfrag * yfrag * src[(yi*swidth+xi)*4+2]; 
     alpha = xfrag * yfrag * src[(yi*swidth+xi)*4+3]; 

     for(i=0; xi + i + 1 < xt+dx-1; i++) 
     { 
     red += yfrag * src[(yi*swidth+xi+i+1)*4]; 
     green += yfrag * src[(yi*swidth+xi+i+1)*4+1]; 
     blue += yfrag * src[(yi*swidth+xi+i+1)*4+2]; 
     alpha += yfrag * src[(yi*swidth+xi+i+1)*4+3]; 
     } 

     red += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4]; 
     green += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+1]; 
     blue += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+2]; 
     alpha += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+3]; 


     for(i=0; yi+i+1 < yt +dy-1 && yi + i+1 < sheight;i++) 
     { 
     red += xfrag * src[((yi+i+1)*swidth+xi)*4]; 
     green += xfrag * src[((yi+i+1)*swidth+xi)*4+1]; 
     blue += xfrag * src[((yi+i+1)*swidth+xi)*4+2]; 
     alpha += xfrag * src[((yi+i+1)*swidth+xi)*4+3]; 

     for (ii = 0; xi + ii + 1 < xt + dx - 1 && xi + ii + 1 < swidth; ii++) 
     { 
      red += src[((yi+i+1)*swidth+xi+ii+1)*4]; 
      green += src[((yi+i+1)*swidth+xi+ii+1)*4+1]; 
      blue += src[((yi+i+1)*swidth+xi+ii+1)*4+2]; 
      alpha += src[((yi+i+1)*swidth+xi+ii+1)*4+3]; 
     } 

      if (yi + i + 1 < sheight && xi + ii + 1 < swidth) 
      { 
       red += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4]; 
       green += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+1]; 
       blue += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+2]; 
       alpha += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+3]; 
      } 
     } 

     if (yi + i + 1 < sheight) 
     { 
      red += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4]; 
      green += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 1]; 
      blue += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 2]; 
      alpha += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 3]; 

      for (ii = 0; xi + ii + 1 < xt + dx - 1 && xi + ii + 1 < swidth; ii++) 
      { 
       red += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4]; 
       green += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 1]; 
       blue += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 2]; 
       alpha += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 3]; 
      } 
     } 

     if (yi + i + 1 < sheight && xi + ii + 1 < swidth) 
     { 
      red += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4]; 
      green += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 1]; 
      blue += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 2]; 
      alpha += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 3]; 
     } 


    red /= dx * dy; 
    green /= dx * dy; 
    blue /= dx * dy; 
    alpha /= dx * dy; 

    red = clamp(red, 0, 255); 
    green = clamp(green, 0, 255); 
    blue = clamp(blue, 0, 255); 
    alpha = clamp(alpha, 0, 255); 

    dest[(y*dwidth+x)*4] = (unsigned char) red; 
    dest[(y*dwidth+x)*4+1] = (unsigned char) green; 
    dest[(y*dwidth+x)*4+2] = (unsigned char) blue; 
    dest[(y*dwidth+x)*4+3] = (unsigned char) alpha; 
    } 
    } 


} 

githubのBaby Xリソースコンパイラで管理されています。

https://github.com/MalcolmMcLean/babyxrc

+0

githubリポジトリにライセンスファイルを含めることができますので、使用可能なユースケースが何であるかは明らかですか?私は1つを見つけることができませんでした....あなたのプロジェクトが多くの人々にとって非常に有用であるように思えます... –

+0

このアルゴリズムの名前は何ですか? –

+0

そのコードは私によって考案され、 "現状のまま" Web上で利用可能です。コードが他の作者の作品に基づいて、または他の作者の作品に基づいて書かれている場合、私はライセンス条項を保持し、もちろん他の人々にそれらを遵守するよう依頼します。アルゴリズムは私によって考案されましたが、オリジナルである可能性は非常に低いです、私はそれを「平均化」方法と呼んでいます。 –

関連する問題