Dev-C++ 4.9.9.2
gcc version 3.4.2 (mingw-special)
です。
画像の拡大と縮小について質問があります。
自作の画像を扱うライブラリ(添付)を使用し、画像を拡大縮小して表示するソフトを作りました。
うまく動いてはいるのですが、画像を大きく拡大すると、少し重いようです。
また、比較のためにStretchBltでの拡大縮小も実装しましたが、
自前のプログラムでは、StretchBltに比べて画像が少し上にあるように見えます。
もうすこしいい(書き方が美しい、実行が速い、綺麗な画像が出力される、のいずれか)
コードにするにはどうすればいいでしょうか?
アドバイスをいただけると嬉しいです。
言語はC言語でお願いします。
よろしくお願いします。
自作のライブラリは、
bmpGetWidth(bmp)で画像の幅を取得します。
bmpGetHeight(bmp)で画像の高さを取得します。
bmpGetXY(bmp,x,y).r
bmpGetXY(bmp,x,y).g
bmpGetXY(bmp,x,y).b
でそれぞれ画像の(x,y)要素(左上が(0,0))の赤、緑、青成分にアクセス(取得、設定)できます。
拡大縮小の部分のコードです。
プロジェクト全体は添付しました。
#include "gstretch.h"
bmp_t* bmp_stretch(const bmp_t* bmp,int width,int height,int hokanflag) {
bmp_t* bmp2;
bmp_t* bmp3;
int i,j,k;
int prev,next,hokan;
int rsum,gsum,bsum;
if(width<=0 || height<=0 || bmp==NULL)return NULL;
if(hokanflag) {
/*補間有効モード*/
bmp2=bmpMake(width,bmpGetHeight(bmp));
if(bmp2==NULL)return NULL;
if(width>bmpGetWidth(bmp)) {
/*拡大なので補間*/
for(i=0;i<bmpGetHeight(bmp);i++) {
for(j=0;j<width;j++) {
prev=j*bmpGetWidth(bmp)/width;
next=prev+1;
if(next>=bmpGetWidth(bmp))next=bmpGetWidth(bmp)-1;
hokan=((j<<10)*bmpGetWidth(bmp)/width)%1024;
bmpGetXY(bmp2,j,i).r=(
bmpGetXY(bmp,prev,i).r*(1024-hokan)+
bmpGetXY(bmp,next,i).r*hokan
)>>10;
bmpGetXY(bmp2,j,i).g=(
bmpGetXY(bmp,prev,i).g*(1024-hokan)+
bmpGetXY(bmp,next,i).g*hokan
)>>10;
bmpGetXY(bmp2,j,i).b=(
bmpGetXY(bmp,prev,i).b*(1024-hokan)+
bmpGetXY(bmp,next,i).b*hokan
)>>10;
}
}
} else if(width<bmpGetWidth(bmp)) {
/*縮小なので平均を取る*/
for(i=0;i<bmpGetHeight(bmp);i++) {
for(j=0;j<width;j++) {
prev=j*bmpGetWidth(bmp)/width;
next=(j+1)*bmpGetWidth(bmp)/width;
rsum=gsum=bsum=0;
for(k=prev;k<next;k++) {
rsum+=bmpGetXY(bmp,k,i).r;
gsum+=bmpGetXY(bmp,k,i).g;
bsum+=bmpGetXY(bmp,k,i).b;
}
bmpGetXY(bmp2,j,i).r=rsum/(next-prev);
bmpGetXY(bmp2,j,i).g=gsum/(next-prev);
bmpGetXY(bmp2,j,i).b=bsum/(next-prev);
}
}
} else {
/*同じ大きさなので単純にコピー*/
for(i=0;i<bmpGetHeight(bmp);i++) {
for(j=0;j<width;j++) {
bmpGetXY(bmp2,j,i).r=bmpGetXY(bmp,j,i).r;
bmpGetXY(bmp2,j,i).g=bmpGetXY(bmp,j,i).g;
bmpGetXY(bmp2,j,i).b=bmpGetXY(bmp,j,i).b;
}
}
}
bmp3=bmpMake(width,height);
if(bmp3==NULL) {
bmpFree(bmp2);
return NULL;
}
if(height>bmpGetHeight(bmp2)) {
/*拡大なので補間*/
for(i=0;i<width;i++) {
for(j=0;j<height;j++) {
prev=j*bmpGetHeight(bmp2)/height;
next=prev+1;
if(next>=bmpGetHeight(bmp2))next=bmpGetHeight(bmp2)-1;
hokan=((j<<10)*bmpGetHeight(bmp2)/height)%1024;
bmpGetXY(bmp3,i,j).r=(
bmpGetXY(bmp2,i,prev).r*(1024-hokan)+
bmpGetXY(bmp2,i,next).r*hokan
)>>10;
bmpGetXY(bmp3,i,j).g=(
bmpGetXY(bmp2,i,prev).g*(1024-hokan)+
bmpGetXY(bmp2,i,next).g*hokan
)>>10;
bmpGetXY(bmp3,i,j).b=(
bmpGetXY(bmp2,i,prev).b*(1024-hokan)+
bmpGetXY(bmp2,i,next).b*hokan
)>>10;
}
}
} else if(height<bmpGetHeight(bmp)) {
/*縮小なので平均を取る*/
for(i=0;i<width;i++) {
for(j=0;j<height;j++) {
prev=j*bmpGetHeight(bmp2)/height;
next=(j+1)*bmpGetHeight(bmp2)/height;
rsum=gsum=bsum=0;
for(k=prev;k<next;k++) {
rsum+=bmpGetXY(bmp2,i,k).r;
gsum+=bmpGetXY(bmp2,i,k).g;
bsum+=bmpGetXY(bmp2,i,k).b;
}
bmpGetXY(bmp3,i,j).r=rsum/(next-prev);
bmpGetXY(bmp3,i,j).g=gsum/(next-prev);
bmpGetXY(bmp3,i,j).b=bsum/(next-prev);
}
}
} else {
/*同じ大きさなので単純にコピー*/
for(i=0;i<width;i++) {
for(j=0;j<height;j++) {
bmpGetXY(bmp3,i,j).r=bmpGetXY(bmp2,i,j).r;
bmpGetXY(bmp3,i,j).g=bmpGetXY(bmp2,i,j).g;
bmpGetXY(bmp3,i,j).b=bmpGetXY(bmp2,i,j).b;
}
}
}
/*中間データを開放*/
bmpFree(bmp2);
} else {
/*補間無効モード*/
bmp3=bmpMake(width,height);
if(bmp3==NULL)return NULL;
for(i=0;i<width;i++) {
for(j=0;j<height;j++) {
int x=i*bmpGetWidth(bmp)/width;
int y=j*bmpGetHeight(bmp)/height;
bmpGetXY(bmp3,i,j).r=bmpGetXY(bmp,x,y).r;
bmpGetXY(bmp3,i,j).g=bmpGetXY(bmp,x,y).g;
bmpGetXY(bmp3,i,j).b=bmpGetXY(bmp,x,y).b;
}
}
}
return bmp3;
}