Created
June 1, 2016 03:16
-
-
Save kunishi/fd819f6e1c3339030a59108053854583 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <time.h> | |
#include "image.h" | |
#define BUFFER_SIZE 256 /* 読み込み Buffer の大きさ */ | |
/* | |
* 画像用メモリの確保 | |
*/ | |
Image *createImage(int width, int height, int channel) | |
{ | |
Image *image = NULL; /* 画像構造体へのポインタ */ | |
/* 画像構造体用メモリの確保 */ | |
image = (Image*)malloc(sizeof(Image)); | |
if (image == NULL) { | |
printf("createImage: Cannot allocate memory for image\n"); | |
} | |
/* 画像情報の設定およびデータ用メモリの確保 */ | |
if (image != NULL) { | |
image->width = width; | |
image->height = height; | |
image->channel = channel; | |
image->data = (unsigned char*)malloc(sizeof(unsigned char) | |
* width * height * channel); | |
if (image->data == NULL) { | |
printf("createImage: Cannot allocate memory for image data\n"); | |
free(image); | |
image = NULL; | |
} else { | |
memset(image->data, 0, width * height * channel); | |
} | |
} | |
/* 画像構造体へのポインタを返す */ | |
return image; | |
} | |
/* | |
* 画像用メモリの解放 | |
*/ | |
void deleteImage(Image *image) | |
{ | |
if (image != NULL) { | |
if (image->data != NULL) { | |
free(image->data); | |
} | |
free(image); | |
} | |
} | |
/* | |
* PPM ファイルの読み込み | |
*/ | |
Image *loadPPM(char *filename) | |
{ | |
Image *image = NULL; /* 画像構造体へのポインタ */ | |
FILE *fp; /* ファイルポインタ */ | |
char buffer[BUFFER_SIZE]; /* 読み込み buffer */ | |
char *tmp; /* token 切り分け用 */ | |
int width, height, channel; /* 画像の幅, 高さ, チャンネル */ | |
if ((fp = fopen(filename, "rb")) == NULL) { | |
printf("loadPPM: Cannot open PPM file \"%s\"\n", filename); | |
} else { | |
/* PPM Header の読み込み */ | |
while ((fgets(buffer, BUFFER_SIZE, fp) != NULL) | |
&& (buffer[0] == '#')) ; | |
if (strncmp(buffer, "P6", 2) == 0) { /* Binary PPM */ | |
channel = 3; | |
} else if (strncmp(buffer, "P5", 2) == 0) { /* Binary PGM */ | |
channel = 1; | |
} else { | |
printf("loadPPM: file \"%s\" may be other than Binary PPM\n", | |
filename); | |
return NULL; | |
} | |
/* 画像の幅の取得 */ | |
while ((fgets(buffer, BUFFER_SIZE, fp) != NULL) | |
&& (buffer[0] == '#')) ; | |
tmp = strtok(buffer, " \t\n"); | |
width = atoi(tmp); /* 画像の幅 */ | |
/* 画像の高さの取得 */ | |
if ((tmp = strtok(NULL, " \t\n")) == NULL) { | |
while ((fgets(buffer, BUFFER_SIZE, fp) != NULL) | |
&& (buffer[0] == '#')) ; | |
tmp = strtok(buffer, " \t\n"); | |
} | |
height = atoi(tmp); /* 画像の高さ */ | |
/* 画像データの大きさの取得(読み飛ばし) */ | |
if ((tmp = strtok(NULL, " \t\n")) == NULL) { | |
while ((fgets(buffer, BUFFER_SIZE, fp) != NULL) | |
&& (buffer[0] == '#')) ; | |
tmp = strtok(buffer, " \t\n"); | |
} | |
/* 画像データの読み込み */ | |
if ((image = createImage(width, height, channel)) != NULL) { | |
fread(image->data, sizeof(unsigned char), | |
width * height * channel, fp); | |
} | |
fclose(fp); | |
} | |
return image; | |
} | |
/* | |
* PPM ファイルの書き出し | |
*/ | |
void savePPM(char *filename, Image *image) | |
{ | |
FILE *fp; /* ファイルポインタ */ | |
if (image == NULL) { | |
printf("savePPM: image is NULL\n"); | |
return; | |
} | |
if ((fp = fopen(filename, "wb")) == NULL) { | |
printf("savePPM: Cannot open PPM file \"%s\"\n", filename); | |
} else { | |
if (image->channel == 3) { | |
fputs("P6\n", fp); /* PPM Header の書き出し */ | |
} else if (image->channel == 1) { | |
fputs("P5\n", fp); /* PGM Header の書き出し */ | |
} else { | |
fclose(fp); | |
return; | |
} | |
fprintf(fp, "%d %d\n", | |
image->width, image->height); /* 幅, 高さ */ | |
fputs("255\n", fp); /* 画像データの大きさ */ | |
/* 画像データの書き出し */ | |
fwrite(image->data, sizeof(unsigned char), | |
image->width * image->height * image->channel, fp); | |
fclose(fp); | |
} | |
} | |
/* | |
* 平滑化フィルタ(平均値フィルタ) | |
*/ | |
void smoothingFilter(Image *src, Image *dst) | |
{ | |
char *funcname = "smoothingFilter"; | |
int i, j, x, y; | |
double sum; | |
double filter[3][3] ={{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0}}; | |
if (src->channel != 1) { | |
printf("%s: original is not gray-scale image\n", funcname); | |
return; | |
} | |
if (dst->channel != 1) { | |
printf("%s: destination is not gray-scale image\n", funcname); | |
return; | |
} | |
if ((src->width != dst->width) || (src->height != dst->height)) { | |
printf("%s: original and destination is not same size\n", funcname); | |
return; | |
} | |
/* フィルタ処理部 */ | |
// ラスタ走査 | |
for (y = 0; y < src->height; y++) { | |
for (x = 0; x < src->width; x++) { | |
// フィルタの積和計算が画像外にはみ出ない範囲でフィルタ処理を適用 | |
if(0<y && y<src->height-1 && 0<x && x<src->width-1 ){ | |
sum = 0.0; | |
for (j = 0; j < 3; j++) | |
for (i = 0; i < 3; i++) | |
sum += PIXEL(src, x+i-1, y+j-1, 0)*filter[i][j]; | |
PIXEL(dst, x, y, 0) = sum; // 周囲 8 マスとの平均値 | |
} | |
else | |
PIXEL(dst, x, y, 0) = PIXEL(src, x, y, 0); | |
} | |
} | |
} | |
void smoothingFilter_omomi(Image *src, Image *dst) | |
{ | |
char *funcname = "smoothingFilter"; | |
int i, j, x, y; | |
double sum; | |
// ここを変えると良い | |
double filter[3][3] ={{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0}}; | |
if (src->channel != 1) { | |
printf("%s: original is not gray-scale image\n", funcname); | |
return; | |
} | |
if (dst->channel != 1) { | |
printf("%s: destination is not gray-scale image\n", funcname); | |
return; | |
} | |
if ((src->width != dst->width) || (src->height != dst->height)) { | |
printf("%s: original and destination is not same size\n", funcname); | |
return; | |
} | |
/* フィルタ処理部 */ | |
// ラスタ走査 | |
for (y = 0; y < src->height; y++) { | |
for (x = 0; x < src->width; x++) { | |
// フィルタの積和計算が画像外にはみ出ない範囲でフィルタ処理を適用 | |
if(0<y && y<src->height-1 && 0<x && x<src->width-1 ){ | |
sum = 0.0; | |
for (j = 0; j < 3; j++) | |
for (i = 0; i < 3; i++) | |
sum += PIXEL(src, x+i-1, y+j-1, 0)*filter[i][j]; | |
PIXEL(dst, x, y, 0) = sum; // 周囲 8 マスとの平均値 | |
} | |
else | |
PIXEL(dst, x, y, 0) = PIXEL(src, x, y, 0); | |
} | |
} | |
} | |
void noiseImg(Image *src, Image *dst) // | |
{ | |
int x, y; | |
int remainder; | |
int r; | |
int p = 20; // ランダムで黒,白になる確率 | |
srand((unsigned)time(NULL)); // 現在時刻で乱数の種を決める | |
for (y = 0; y < src->height; y++) | |
for (x = 0; x < src->width; x++){ | |
r = rand(); | |
/* | |
remainder = r % p; | |
printf("%d\n", remainder); | |
if(remainder == 0) | |
PIXEL(dst, x, y, 0) = 0; | |
else if(remainder == 1) | |
PIXEL(dst, x, y, 0) = MAX; | |
else PIXEL(dst, x, y, 0) = PIXEL(src, x, y, 0); | |
*/ | |
} | |
} | |
void affine(Image *src, Image *dst, float theta, float sx, float sy, float tx, float ty) | |
/* | |
引数リスト: | |
Image *src, *dst: 入力画像, 出力画像 | |
float theta: 回転角(度) | |
float sx, sy: 拡大縮小率 | |
float tx, ty: 平行移動量 | |
*/ | |
{ | |
int x, y, inte_x, inte_y; | |
int sift_x, sift_y, orig_x, orig_y; | |
float c, s, r; | |
float affi_x, affi_y; | |
r = -theta*3.141592/180.0; | |
c = (float)cos(r); // うえ逆 | |
s = (float)sin(r); | |
// 入力画像(変換前)の全ての画素に対して処理(2重for文) | |
for(y=0; y<dst->height; y++){ | |
for(x=0; x<dst->width; x++){ | |
// 原点を移動(原点は画像の中心) | |
orig_x = x - src->width/2; | |
orig_y = y - src->height/2; | |
// 平行移動(sift_x, sift_y : 平行移動後の座標) /////kaeru | |
sift_x = orig_x - tx; | |
sift_y = orig_y - ty; | |
// 回転・拡大縮小(affi_x, affi_y : アフィン変換後の座標)/////kaeru | |
affi_x = (sift_x*c - sift_y*s) / sx; | |
affi_y = (sift_x*s + sift_y*c) / sy; | |
/* 元の式 | |
affi_x = (sift_x*c - sift_y*s) * sx; | |
affi_y = (sift_x*s + sift_y*c) * sy; | |
*/ | |
/* 小さくなる | |
affi_x = (sift_x/sx + sift_y*s)/c ; | |
affi_y = (sift_y/sy - sift_x*s)/c ; | |
*/ | |
// affi_y = sift_y*c/sy - sift_x*s/sx; | |
// affi_x = sift_y*s/sy + sift_x*c/sx ; | |
// affi_x = (sift_x/sx + affi_y*s)/c ; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
// 補間後の座標について、変換前の画像サイズに収まる場合 | |
if( (0<=inte_x) && (inte_x<src->width) && (0<=inte_y) && (inte_y<src->height) ) | |
{ | |
PIXEL(dst, x, y, 0) = PIXEL(src, inte_x, inte_y, 0); ////////kaeery | |
//PIXEL(dst, inte_x, inte_y, 0) = PIXEL(src, x, y, 0); | |
} | |
} | |
} | |
} | |
void affine_2(Image *src, Image **dst, float theta, float sx, float sy, float tx, float ty) | |
/* | |
引数リスト: | |
Image *src, *dst: 入力画像, 出力画像 | |
float theta: 回転角(度) | |
float sx, sy: 拡大縮小率 | |
float tx, ty: 平行移動量 | |
*/ | |
{ | |
int x, y, inte_x, inte_y; | |
int sift_x, sift_y, orig_x, orig_y; | |
float c, s, r; | |
float affi_x, affi_y; | |
r = theta*3.141592/180.0; | |
c = (float)cos(r); // 逆 | |
s = (float)sin(r); | |
/* 出力画像のサイズを取得 */ | |
x = 0, y = 0; | |
orig_x = x - src->width/2; | |
orig_y = y - src->height/2; | |
sift_x = orig_x + tx; | |
sift_y = orig_y + ty; | |
affi_x = (sift_x*c - sift_y*s) * sx; | |
affi_y = (sift_x*s + sift_y*c) * sy; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
printf("%d, %d\n", inte_x, inte_y); | |
// dst = createImage(180, 230, 1); | |
*dst = createImage(180, 230, 1); | |
// 入力画像(変換前)の全ての画素に対して処理(2重for文) | |
for(y=0; y<(*dst)->height; y++){ // scr から dst へ変更 | |
for(x=0; x<(*dst)->width; x++){ | |
// 原点を移動(原点は画像の中心) | |
orig_x = x - src->width/2; | |
orig_y = y - src->height/2; | |
// 平行移動(sift_x, sift_y : 平行移動後の座標) /////kaeru | |
sift_x = orig_x - tx; | |
sift_y = orig_y - ty; | |
// 回転・拡大縮小(affi_x, affi_y : アフィン変換後の座標)/////kaeru | |
affi_x = (sift_x*c - sift_y*s) / sx; | |
affi_y = (sift_x*s + sift_y*c) / sy; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
// 補間後の座標について、変換前の画像サイズに収まる場合 | |
/* | |
while(inte_x > 0 || inte_x>src->width) | |
dst->width+100; | |
*/ | |
// ↓Segmentationfault | |
// if( (0<x) && (x<src->width) && (0<=y) && (y<src->height) ) { | |
if( (0<inte_x) && (inte_x<src->width) && (0<=inte_y) && (inte_y<src->height) ) | |
PIXEL(*dst, x, y, 0) = PIXEL(src, inte_x, inte_y, 0); ////////kaeery | |
//PIXEL(dst, inte_x, inte_y, 0) = PIXEL(src, x, y, 0); | |
// } | |
} | |
} | |
} | |
void affine_3(Image *src, Image *dst, float theta, float sx, float sy, float tx, float ty) | |
/* | |
引数リスト: | |
Image *src, *dst: 入力画像, 出力画像 | |
float theta: 回転角(度) | |
float sx, sy: 拡大縮小率 | |
float tx, ty: 平行移動量 | |
*/ | |
{ | |
int x, y, inte_x, inte_y; | |
int sift_x, sift_y, orig_x, orig_y; | |
float c, s, r; | |
float affi_x, affi_y; | |
r = theta*3.141592/180.0; | |
c = (float)cos(-r); // 逆 | |
s = (float)sin(-r); | |
/* 出力画像のサイズを取得 */ | |
x = 0, y = 0; | |
// x = src->width, y = 0; | |
//x = 0, y = src->height; | |
// x = src->width, y = src->height; | |
orig_x = x - src->width/2; | |
orig_y = y - src->height/2; | |
sift_x = orig_x + tx; | |
sift_y = orig_y + ty; | |
affi_x = (sift_x*c - sift_y*s) * sx; | |
affi_y = (sift_x*s + sift_y*c) * sy; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
printf("%d, %d\n", inte_x, inte_y); // ok マイナスになることもある, 点の対応はよく分からない | |
// 入力画像(変換前)の全ての画素に対して処理(2重for文) | |
for(y=0; y<dst->height; y++){ | |
for(x=0; x<dst->width; x++){ | |
// 原点を移動(原点は画像の中心) | |
orig_x = x - src->width/2; | |
orig_y = y - src->height/2; | |
// 平行移動(sift_x, sift_y : 平行移動後の座標) /////kaeru | |
sift_x = orig_x - tx; | |
sift_y = orig_y - ty; | |
// 回転・拡大縮小(affi_x, affi_y : アフィン変換後の座標)/////kaeru | |
affi_x = (sift_x*c - sift_y*s) / sx; | |
affi_y = (sift_x*s + sift_y*c) / sy; | |
// 平行移動で調整(追加) | |
affi_x = affi_x - 234/2; | |
affi_y = affi_y + 128/2; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
/* これじゃない | |
// 平行移動で調整(追加) | |
inte_x = inte_x -234; | |
inte_y = inte_y - 128; | |
*/ | |
// 補間後の座標について、変換前の画像サイズに収まる場合 | |
if( (0<=inte_x) && (inte_x<src->width) && (0<=inte_y) && (inte_y<src->height) ) | |
{ | |
PIXEL(dst, x, y, 0) = PIXEL(src, inte_x, inte_y, 0); ////////kaeery | |
//PIXEL(dst, inte_x, inte_y, 0) = PIXEL(src, x, y, 0); | |
} | |
} | |
} | |
} | |
void convertRGBtoGray(Image *rgb, Image *gray) | |
{ | |
int x, y; | |
for(x=0; x< rgb->width ; x++) | |
for(y=0; y< rgb->height ; y++){ | |
PIXEL(gray, x, y, 0) = PIXEL(rgb, x, y, 0) * 0.299 | |
+ PIXEL(rgb, x, y, 0) * 0.587 | |
+ PIXEL(rgb, x, y, 0) * 0.114; | |
} | |
} | |
void rotation(int *x, int *y, int theta) | |
{ | |
int orig_x = *x, orig_y = *y; | |
float c, s, r; | |
float affi_x, affi_y; | |
r = theta*3.141592/180.0; | |
c = (float)cos(r); // 逆 | |
s = (float)sin(r); | |
*x = orig_x*c - orig_y*s; | |
*y = orig_x*s + orig_y*c; | |
} | |
void shift(int *x, int *y, int tx, int ty) | |
{ | |
int orig_x = *x, orig_y = *y; | |
float c, s, r; | |
float affi_x, affi_y; | |
*x = orig_x + tx; | |
*y = orig_y + ty; | |
} | |
void scaling(int *x, int *y, int sx, int sy) | |
{ | |
int orig_x = *x, orig_y = *y; | |
float c, s, r; | |
float affi_x, affi_y; | |
*x = orig_x * sx; | |
*y = orig_y * sy; | |
} | |
void size(float *width, float *height, corner *C, Affine Affi) | |
{ | |
float r, c, s; | |
corner tmp_C; | |
tmp_C.A_x = C->A_x; | |
tmp_C.A_y = C->A_y; | |
tmp_C.B_x = C->B_x; | |
tmp_C.B_y = C->B_y; | |
tmp_C.C_x = C->C_x; | |
tmp_C.C_y = C->C_y; | |
tmp_C.D_x = C->D_x; | |
tmp_C.D_y = C->D_y; | |
//printf("%f\n", Affi.theta); | |
r = Affi.theta*3.141592/180.0; | |
c = (float)cos(r); // 逆 | |
s = (float)sin(r); | |
*width = Affi.theta + 4.0; // test | |
*height = Affi.theta + 10.0; | |
C->A_x = Affi.sx*c*tmp_C.A_x - Affi.sy*s*tmp_C.A_y; | |
C->A_y = Affi.sx*s*tmp_C.A_x + Affi.sy*c*tmp_C.A_y; | |
C->B_x = Affi.sx*c*tmp_C.B_x - Affi.sy*s*tmp_C.B_y; | |
C->B_y = Affi.sx*s*tmp_C.B_x + Affi.sy*c*tmp_C.B_y; | |
C->C_x = Affi.sx*c*tmp_C.C_x - Affi.sy*s*tmp_C.C_y; | |
C->C_y = Affi.sx*s*tmp_C.C_x + Affi.sy*c*tmp_C.C_y; | |
C->D_x = Affi.sx*c*tmp_C.D_x - Affi.sy*s*tmp_C.D_y; | |
C->D_y = Affi.sx*s*tmp_C.D_x + Affi.sy*c*tmp_C.D_y; | |
/* | |
printf("A (%f, %f)\n", *C.A_x, *C.A_y); | |
printf("B (%f, %f)\n", *C.B_x, *C.B_y); | |
printf("C (%f, %f)\n", *C.C_x, *C.C_y); | |
printf("D (%f, %f)\n", *C.D_x, *C.D_y); | |
printf("%f\n", *C.A_x - *C.C_x); | |
printf("%f\n", *C.B_x - *C.D_x); | |
printf("%f\n", *C.A_y - *C.C_y); | |
printf("%f\n\n", *C.B_y - *C.D_y); | |
*/ | |
if(fabs(C->A_x - C->C_x) >= fabs(C->B_x - C->D_x)) | |
*width = fabs(C->A_x - C->C_x); | |
else *width = fabs(C->B_x - C->D_x); | |
if(fabs(C->A_y - C->C_y) >= fabs(C->B_y - C->D_y)) | |
*height = fabs(C->A_y - C->C_y); | |
else *height = fabs(C->B_y - C->D_y); | |
} | |
// 対話式にしたい (平行移動なし) // 繰り返し変換 | |
void my_affine_9(Image *src, Image *dst, Affine Affi) | |
{ | |
int x, y, inte_x, inte_y; | |
int sift_x, sift_y, orig_x, orig_y; | |
float c, s, r; | |
float affi_x, affi_y; | |
// float W, H, adjust_x = 0, adjust_y = 0; | |
float W, H; | |
// float tmp_theta = 0, tmp_sx=1, tmp_sy=1; | |
float dx, dy, f_00, f_01, f_10, f_11, pixel; // 線形補間法 | |
Image *tmp_img; | |
// Affine Affi; | |
// Affi.theta = 0, Affi.sx = 1, Affi.sy = 1; | |
corner Corner, tmp_Corner; | |
Corner.A_x = 0, Corner.A_y = 0; | |
Corner.B_x = src->width, Corner.B_y = 0; | |
Corner.C_x = src->width, Corner.C_y = src->height; | |
Corner.D_x = 0, Corner.D_y = src->height; | |
r = -Affi.theta*3.141592/180.0; | |
c = (float)cos(r); // 逆 | |
s = (float)sin(r); | |
// while(1) // 1 回めはコピー | |
// { | |
// r = -Affi.theta*3.141592/180.0; | |
// c = (float)cos(r); // 逆 | |
// s = (float)sin(r); | |
tmp_Corner = Corner; | |
size(&W, &H, &Corner, Affi); | |
//deleteImage(dst); | |
//dst = createImage((int)W +1, (int)H+1 , 1); // リサイズ +1?? | |
// 出力画像(変換前)の全ての画素に対して処理(2重for文) | |
for(y=0; y<dst->height; y++) | |
for(x=0; x<dst->width; x++){ | |
// 原点を移動(原点は画像の中心) | |
orig_x = x - dst->width/2; // 変更!! | |
orig_y = y - dst->height/2; | |
// アフィン変換 | |
affi_x = orig_x*c/Affi.sx - orig_y*s/Affi.sx; | |
affi_y = orig_x*s/Affi.sy + orig_y*c/Affi.sy; | |
// 最近傍法(inte_x, inte_y : 補間後の座標 | |
if( affi_x>0 ) inte_x = (int)( affi_x+0.5 ); // 四捨五入 | |
else inte_x = (int)( affi_x-0.5 ); | |
if( affi_y>0 ) inte_y = (int)( affi_y+0.5 ); | |
else inte_y = (int)( affi_y-0.5 ); | |
// 原点を移動(原点は画像の左上) | |
inte_x = inte_x + src->width/2; | |
inte_y = inte_y + src->height/2; | |
// 補間後の座標について、変換前の画像サイズに収まる場合 | |
if( (0<=inte_x) && (inte_x<src->width) && (0<=inte_y) && (inte_y<src->height) ) { | |
PIXEL(dst, x, y, 0) = PIXEL(src, inte_x, inte_y, 0); ////////kaeery | |
} | |
} | |
// savePPM("resizedImg.ppm", dst); | |
// | |
// scanf("%f", &Affi.theta); // 次の引数を取得 | |
// scanf("%f", &Affi.sx); // 倍率 0 の時メッセージ? | |
// scanf("%f", &Affi.sy); | |
// | |
// if(Affi.theta == 0 && Affi.sx == 1 && Affi.sy == 1) | |
// break; | |
// | |
// | |
// tmp_img = dst; // dst を次の src にする | |
// dst = src; | |
// | |
// for(x=0; x< dst->width ; x++) // src に dst をコピー | |
// for(y=0; y< dst->height ; y++) | |
// PIXEL(src, x, y, 0) = PIXEL(dst, x, y, 0); | |
// | |
// src = tmp_img; | |
// } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <math.h> | |
/* | |
* 画像構造体 | |
*/ | |
typedef struct Image { | |
int width; /* 画像の幅 */ | |
int height; /* 画像の高さ */ | |
int channel; /* 画像のチャンネル数 */ | |
unsigned char *data; /* 画像データ */ | |
} Image; | |
typedef struct corner{ // 画像の四隅の座標 | |
float A_x, A_y, B_x, B_y, C_x, C_y, D_x, D_y; | |
} corner; | |
typedef struct Affine{ // 変換の引数 | |
float theta, sx, sy; | |
} Affine; | |
/* | |
* 関数群のプロトタイプ宣言 | |
*/ | |
Image *createImage(int width, int height, int channel); | |
void deleteImage(Image *image); | |
Image *loadPPM(char *filename); | |
void savePPM(char *filename, Image *image); | |
void smoothingFilter(Image *src, Image *dst); | |
void affine(Image *src, Image *dst, float theta, float sx, float sy, float tx, float ty); | |
void affine_2(Image *src, Image **dst, float theta, float sx, float sy, float tx, float ty); | |
void affine_3(Image *src, Image *dst, float theta, float sx, float sy, float tx, float ty); | |
void size(float *width, float *height, corner *C, Affine Afii); | |
void my_affine_9(Image *src, Image *dst, Affine Affi); | |
/* | |
* macro | |
*/ | |
#define PIXEL(i,x,y,c) \ | |
(*(((i)->data)+((y)*((i)->width)+(x))*((i)->channel)+(c))) | |
void convertRGBtoGray(Image *rgb, Image *gray); | |
void scaling(int *x, int *y, int sx, int sy); | |
void shift(int *x, int *y, int tx, int ty); | |
void rotation(int *x, int *y, int theta); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "image.h" | |
int main(void) | |
{ | |
Image *img1, *img2, **img3, *img4, *img5; | |
img1 = loadPPM("./lenna_2.ppm"); | |
img2 = createImage(img1->width, img1->height, 1); | |
//img3 = createImage(img1->width, img1->height, 1); | |
img4 = createImage(img2->width, img2->height, 1); | |
img5 = createImage(img1->width*2, img2->width*2, 1); | |
convertRGBtoGray(img1, img2); | |
// affine_2( img2, img3, 0.0, 0.7 , 0.9 , 30, 40 ); | |
Image *src = img2; | |
Image *dst = img4; | |
Image *tmp_img; | |
int x, y; | |
Affine Affi; | |
Affi.theta = 0, Affi.sx = 1, Affi.sy = 1; | |
while(1) // 1 回めはコピー | |
{ | |
my_affine_9(src, dst, Affi); // y 方向はマイナスに | |
savePPM("resizedImg.ppm", dst); | |
scanf("%f", &Affi.theta); // 次の引数を取得 | |
scanf("%f", &Affi.sx); // 倍率 0 の時メッセージ? | |
scanf("%f", &Affi.sy); | |
if(Affi.theta == 0 && Affi.sx == 1 && Affi.sy == 1) | |
break; | |
tmp_img = dst; // dst を次の src にする | |
dst = src; | |
for(x=0; x< dst->width ; x++) // src に dst をコピー | |
for(y=0; y< dst->height ; y++) | |
PIXEL(src, x, y, 0) = PIXEL(dst, x, y, 0); | |
src = tmp_img; | |
} | |
//my_affine_4(img2, img4); | |
// affine( img2, img3, 90.0, 0.7 , 0.9 , 30, -10 ); | |
savePPM("grayImg.ppm", img2); | |
// savePPM("2_3resizedImg.ppm", *img3); | |
//savePPM("resizedImg.ppm", img4); | |
// 繰り返し適用のテスト | |
/* int x; | |
scanf("%d",&x); | |
my_affine( img4, img5, 140, 0.7 , 0.9 , 30, -10 ); | |
savePPM("KONDOKOSO_resizedImg_re.ppm", img5); | |
*/ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment