fork download
  1. // cs160_861.c
  2. // http://i...content-available-to-author-only...e.com/gN66JU
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. // [名前]
  7. // cs160_861 : RGB → HSV
  8. // [機能]
  9. // RGBの3枚のグレースケールから
  10. // HSVの3枚のグレースケールを出力する
  11. // [資料]
  12. // http://c...content-available-to-author-only...d.org/oNUxByE7
  13. // http://j...content-available-to-author-only...a.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93#RGB.E3.81.8B.E3.82.89HSV.E3.81.B8.E3.81.AE.E5.A4.89.E6.8F.9B
  14. // [コマンドオプション]
  15. // argv[1] : 幅
  16. // argv[2] : 高さ
  17. // argv[3] : 入力 R ファイル名
  18. // argv[4] : 入力 G ファイル名
  19. // argv[5] : 入力 B ファイル名
  20. // argv[6] : 出力Hファイル名
  21. // argv[7] : 出力Sファイル名
  22. // argv[8] : 出力Vファイル名
  23. // [入出力ファイルの仕様]
  24. // 入力RGBファイル
  25. // ・R,G,B それぞれ1ファイルである
  26. // ・HEADER 512 bytes
  27. // ・1dotにつき、百分率16bitリトルエンディアン (0~65535 [100%(65536)は存在しないこととする])
  28. // 出力HSVファイル
  29. // ・H,S,V それぞれ1ファイルである
  30. // ・HEADER 無し
  31. // ・1dotにつき、百分率16bitリトルエンディアン (0~65535 [65535が100%である])
  32. // H (0.0以上 360.0以下) ~ H値 / 360.0 * 65535
  33. // S (0.0以上 1.0以下) ~ S値 * 65535
  34. // V (0.0以上 1.0以下) ~ V値 * 65535
  35. // ※未定義の場合は0x0000をセットする
  36.  
  37.  
  38. // 定数
  39. const int header_size_rgb_file = 512; // RGBファイルのヘッダサイズ
  40. const int comvert_mode = 1; // 変換モード (1:円柱モデル変換, 2:円錐モデル変換)
  41. // fopen(); のモード
  42. #ifdef _WIN32
  43. // Windows
  44. #define FOPEN_MODE_R "rb"
  45. #define FOPEN_MODE_W "wb"
  46. #else
  47. // Linux
  48. #define FOPEN_MODE_R "r"
  49. #define FOPEN_MODE_W "w"
  50. #endif
  51.  
  52. enum ERR_CODE // エラーコード
  53. {
  54. ERR_Normal = 0 , // 正常終了
  55. ERR_Option , // 起動オプションが足りない
  56. ERR_Width , // 入力幅が1未満
  57. ERR_Height , // 入力高が1未満
  58. ERR_InFile_Size , // 入力ファイルサイズが変である
  59. // 以下6個は並び順を変えないこと →→→→→→→→
  60. ERR_InFile_R , // 入力Rファイルオープンエラー
  61. ERR_InFile_G , // 入力Gファイルオープンエラー
  62. ERR_InFile_B , // 入力Bファイルオープンエラー
  63. ERR_OutFile_H , // 出力Hファイルオープンエラー
  64. ERR_OutFile_S , // 出力Sファイルオープンエラー
  65. ERR_OutFile_V , // 出力Vファイルオープンエラー
  66. // ←←←←←←←←←←←←←←←←←←←←←←←
  67. ERR_MemAlloc , // メモリ確保エラー
  68. ERR_Cnv_mode , // cnv_rgb2hsv();でcomvert_modeに不正な値がセットされていた(Prog Error)
  69. };
  70.  
  71. // 中でやり取りするデータ
  72. typedef struct
  73. {
  74. // 幅、高さ
  75. int width, height;
  76. int img_size;
  77. // 入出力 ファイル
  78. FILE * fp_in[3];
  79. FILE * fp_out[3];
  80. // データ
  81. unsigned short *src[3]; // [0]R, [1]G, [2]B
  82. unsigned short *dst[3]; // [0]H, [1]S, [2]V
  83. } RGB_HSV_DATA;
  84.  
  85.  
  86. // 関数
  87. extern void load_rgb_data(RGB_HSV_DATA* data); // Load
  88. extern int cnv_rgb2hsv(RGB_HSV_DATA* data); // Convert
  89. extern int save_hsv_data(RGB_HSV_DATA* data); // Save
  90. extern void get_max_min_mxcolor // max, min, maxのcolor を調べる
  91. ( /*[in]*/unsigned short R, unsigned short G, unsigned short B,
  92. /*[out]*/unsigned short *mx, unsigned short *mn, char *mxcolor );
  93. #define MIN(x, y) ((x)<(y) ? (x) : (y)) // 2値の最小値
  94. #define MIN3(x, y, z) MIN(MIN((x), (y)), (z)) // 3値の最小値
  95.  
  96. // グローバル
  97. char g_flagEndian; // 現在の環境のエンディアン (0:ビッグ / 1:リトル)
  98.  
  99.  
  100. /****************************************************************************
  101.  * main
  102.  ****************************************************************************/
  103. int main(int argc, char *argv[])
  104. {
  105. int res; // 終了コード
  106. RGB_HSV_DATA rh_data; // RGB,HSV データ
  107. int i; // 汎用
  108.  
  109. /*
  110.   * 初期化 & ファイルオープン & チェック
  111.   */
  112. i = 1;g_flagEndian = *((char *)(&i)); // 現在の環境のエンディアン判定 (0:ビッグ / 1:リトル)
  113. memset(&rh_data, 0x00, sizeof(RGB_HSV_DATA));
  114. res = ERR_Normal;
  115. if(argc != 9)
  116. {
  117. res = ERR_Option;
  118. goto ERR_END;
  119. }
  120. // 幅
  121. rh_data.width = atoi (argv[1]);
  122. if(rh_data.width < 0)
  123. {
  124. res = ERR_Width;
  125. goto ERR_END;
  126. }
  127. // 高さ
  128. rh_data.height = atoi (argv[2]);
  129. if(rh_data.height < 0)
  130. {
  131. res = ERR_Height;
  132. goto ERR_END;
  133. }
  134. rh_data.img_size = rh_data.width * rh_data.height;
  135. // ファイルオープン
  136. for(i=0;i<3;i++)
  137. {
  138. if(NULL == (rh_data.fp_in[i] = fopen(argv[3+i], FOPEN_MODE_R)))
  139. {
  140. res = ERR_InFile_R + i;
  141. goto ERR_END;
  142. }
  143. }
  144. for(i=0;i<3;i++)
  145. {
  146. if(NULL==(rh_data.fp_out[i]=fopen(argv[6+i], FOPEN_MODE_W)))
  147. {
  148. res = ERR_OutFile_H + i;
  149. goto ERR_END;
  150. }
  151. }
  152. // ファイルサイズチェック
  153. for(i=0;i<3;i++)
  154. {
  155. fseek(rh_data.fp_in[i], 0, SEEK_END);
  156. if(ftell(rh_data.fp_in[i]) != rh_data.img_size * sizeof(unsigned short) + header_size_rgb_file)
  157. {
  158. res = ERR_InFile_Size;
  159. goto ERR_END;
  160. }
  161. }
  162.  
  163. /*
  164.   * メモリ確保
  165.   */
  166. for(i=0; i<3; i++)
  167. {
  168. if(NULL == (rh_data.src[i] = (unsigned short*)malloc(rh_data.img_size*sizeof(unsigned short))))
  169. {
  170. res = ERR_MemAlloc;
  171. goto ERR_END;
  172. }
  173. if(NULL == (rh_data.dst[i] = (unsigned short*)malloc(rh_data.img_size*sizeof(unsigned short))))
  174. {
  175. res = ERR_MemAlloc;
  176. goto ERR_END;
  177. }
  178. }
  179.  
  180. /*
  181.   * ロード
  182.   */
  183. load_rgb_data(&rh_data);
  184.  
  185. /*
  186.   * 変換
  187.   */
  188. res = cnv_rgb2hsv(&rh_data);
  189. if(ERR_Normal != res)
  190. {
  191. goto ERR_END;
  192. }
  193.  
  194. /*
  195.   * セーブ
  196.   */
  197. res = save_hsv_data(&rh_data);
  198. if(ERR_Normal != res)
  199. {
  200. goto ERR_END;
  201. }
  202.  
  203. /*
  204.   * 終了
  205.   */
  206. res = ERR_Normal;
  207. ERR_END:;
  208. // 解放
  209. for(i=0;i<3;i++)
  210. {
  211. if(rh_data.dst[i]) { free(rh_data.dst[i]); rh_data.dst[i] = NULL; }
  212. if(rh_data.src[i]) { free(rh_data.src[i]); rh_data.src[i] = NULL; }
  213. if(rh_data.fp_out[i]) { fclose(rh_data.fp_out[i]); rh_data.fp_out[i] = NULL; }
  214. if(rh_data.fp_in [i]) { fclose(rh_data.fp_in [i]); rh_data.fp_in [i] = NULL; }
  215. }
  216. return res;
  217. }
  218.  
  219. // Load
  220. void load_rgb_data(RGB_HSV_DATA* data)
  221. {
  222. int i, j;
  223. unsigned short *p, v;
  224.  
  225. for(i=0; i<3; i++)
  226. {
  227. fseek(data->fp_in[i], header_size_rgb_file, SEEK_SET);
  228. fread(data->src[i], sizeof(unsigned short), data->img_size, data->fp_in[i]); // 全部読む
  229. if(0 == g_flagEndian)
  230. {
  231. // big endian (入れ替える必要がある)
  232. p = data->src[i];
  233. for(j=0; j<data->img_size; j++)
  234. {
  235. v = *p;
  236. *p++ = ((v >> 8) & 0xFF) | ((v << 8) & 0xFF00);
  237. }
  238. }
  239. }
  240. }
  241.  
  242. // Save
  243. int save_hsv_data(RGB_HSV_DATA* data)
  244. {
  245. int i, j;
  246. unsigned short *temp = NULL; // エンディアン変換バッファ
  247. unsigned short *p, v;
  248.  
  249. // 確保
  250. if(0 == g_flagEndian)
  251. {
  252. // big endian
  253. if(NULL == (temp = (unsigned short*)malloc(data->img_size * sizeof(unsigned short))))
  254. {
  255. return ERR_MemAlloc;
  256. }
  257. }
  258. // 書き込み
  259. for(i=0; i<3; i++)
  260. {
  261. fseek(data->fp_out[i],0,SEEK_SET);
  262. if(0 == g_flagEndian)
  263. {
  264. memcpy(temp, &(data->dst[i][0]), sizeof(unsigned short) * data->img_size);
  265. p = temp;
  266. for(j=0; j<data->img_size; j++)
  267. {
  268. v = *p;
  269. *p++ = ((v >> 8) & 0xFF) | ((v << 8) & 0xFF00);
  270. }
  271. p = temp;
  272. } else {
  273. p = &(data->dst[i][0]);
  274. }
  275. fwrite(p, sizeof(unsigned short), data->img_size, data->fp_out[i]);
  276. }
  277. // 解放
  278. if(temp)
  279. {
  280. free(temp);
  281. }
  282. return 0;
  283. }
  284.  
  285. // max, min, maxのcolor を調べる
  286. // mxcolor = 'R', 'G', 'B'のいずれか
  287. void get_max_min_mxcolor(/*[in]*/unsigned short R, unsigned short G, unsigned short B, /*[out]*/unsigned short *mx, unsigned short *mn, char *mxcolor)
  288. {
  289. // max
  290. *mx = R; *mxcolor='R';
  291. if(G > *mx) { *mx = G; *mxcolor='G'; }
  292. if(B > *mx) { *mx = B; *mxcolor='B'; }
  293. // min
  294. *mn = MIN3(R, G, B);
  295. }
  296.  
  297. // Convert
  298. int cnv_rgb2hsv(RGB_HSV_DATA* data)
  299. {
  300. unsigned short max, min;
  301. char color_max; // maxの色 ('R','G','B')
  302. unsigned short H,S,V; // HSV
  303. double th; // H計算用
  304. double sub_maxmin; // H計算用 (max - min)
  305. int i; // 汎用
  306.  
  307. for(i=0; i<data->img_size; i++)
  308. {
  309. // max, min, maxの色を取得
  310. get_max_min_mxcolor(data->src[0][i], data->src[1][i], data->src[2][i], &max, &min, &color_max);
  311.  
  312. // SVを求める
  313. // ( http://j...content-available-to-author-only...a.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93#RGB.E3.81.8B.E3.82.89HSV.E3.81.B8.E3.81.AE.E5.A4.89.E6.8F.9B )
  314. V = max;
  315. if(max == min)
  316. {
  317. S = 0;
  318. }else{
  319. if(max == 0)
  320. {
  321. S = 0; // 未定義である
  322. }else{
  323. if(comvert_mode == 1)
  324. {
  325. S = (unsigned short)((double)(max - min) / (double)max * 65535.0);
  326. }
  327. else if(comvert_mode == 2)
  328. {
  329. S = max - min;
  330. } else {
  331. return ERR_Cnv_mode;
  332. }
  333. }
  334. }
  335. // Hを求める
  336. if(max == min)
  337. {
  338. th = 0.0; // 未定義である
  339. }else{
  340. sub_maxmin = (double)max - (double)min;
  341. switch(color_max)
  342. {
  343. case 'R':th = 60.0 * ((double)data->src[1][i] - (double)data->src[2][i]) / sub_maxmin + 0.0;break;
  344. case 'G':th = 60.0 * ((double)data->src[2][i] - (double)data->src[0][i]) / sub_maxmin + 120.0;break;
  345. case 'B':th = 60.0 * ((double)data->src[0][i] - (double)data->src[1][i]) / sub_maxmin + 240.0;break;
  346. }
  347. }
  348. // 0.0以上360.0未満に丸める
  349. while(th < 0.0)
  350. {
  351. th += 360.0;
  352. }
  353. while(th >= 360.0)
  354. {
  355. th -= 360.0;
  356. }
  357. H = (unsigned short)(th / 360.0 * 65535.0); // 360.0の百分率を16bit化
  358. // HSVをセットする
  359. data->dst[0][i] = H;
  360. data->dst[1][i] = S;
  361. data->dst[2][i] = V;
  362. }
  363. return ERR_Normal;
  364. }
  365.  
  366. // End of cs160_861.c
  367.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty