直接 PO 代码:
1 #include <stdio.h> 2 #include <math.h> 3 #include "graphics.h" 4 5 6 /* 三通道数据,用于保存RGB或HSI图像数据 */ 7 typedef struct { 8 double *channel1; 9 double *channel2; 10 double *channel3; 11 } ThreeChannels; 12 /* 三通道数据的初始化 */ 13 void InitThreeChannels(ThreeChannels &tc, int w, int h) { 14 tc.channel1 = (double *)malloc(w*h*sizeof(double)); 15 tc.channel2 = (double *)malloc(w*h*sizeof(double)); 16 tc.channel3 = (double *)malloc(w*h*sizeof(double)); 17 } 18 /* 三通道数据的释放 */ 19 void FreeThreeChannels(ThreeChannels &tc) { 20 free(tc.channel1); 21 free(tc.channel2); 22 free(tc.channel3); 23 } 24 25 /* 26 功能: 在整型数组中找到最小值和最大值 27 输入: 整型数组;数组大小;接收最小值;接收最大值 28 结果: 得到数组中的最小值和最大值 29 */ 30 void GetMinMaxInt(int *arr, int n, int &min, int &max); 31 /* 32 功能: 在浮点型数组中找到最小值和最大值 33 输入: 浮点型数组;数组大小;接收最小值;接收最大值 34 结果: 得到数组中的最小值和最大值 35 */ 36 void GetMinMaxDouble(double *arr, int n, double &min, double &max); 37 /* 38 功能: 打印RGB彩色图像 39 输入: ThreeChannels三通道数据的结构体,宽高 40 结果: 打印RGB彩色图像 41 */ 42 void PrintRGBImage(ThreeChannels &tc, int w, int h); 43 /* 44 功能: 根据文件名获取RGB彩色图像 45 输入: 文件名;ThreeChannels三通道数据的结构体,宽高;是否打印图像 46 结果: 将获取到的RGB图像保存在ThreeChannels结构体中 47 */ 48 void GetImageRGB(char *file, ThreeChannels &tc, int w, int h, int mode); 49 /* 50 功能: RGB转为HSI 51 输入: RGB三通道结构体,HSI三通道结构体 52 结果: 将RGB三通道转为HSI三通道 53 */ 54 void RGB2HSI(ThreeChannels &rgb, int w, int h, ThreeChannels &hsi); 55 /* 56 功能: HSI转为RGB 57 输入: HSI三通道结构体,RGB三通道结构体 58 结果: 将HSI三通道转为RGB三通道 59 */ 60 void HSI2RGB(ThreeChannels &hsi, int w, int h, ThreeChannels &rgb); 61 62 63 int main() { 64 int w=972, h=607; 65 char file_name[] = "kanna.jpg"; 66 67 initgraph(w, h, 0); 68 setcaption("RGB与HSI相互转换"); 69 70 ThreeChannels imgRGB; 71 InitThreeChannels(imgRGB, w, h); 72 73 // 获取RGB彩色图像 74 GetImageRGB(file_name, imgRGB, w, h, 0); 75 76 // RGB转为HSI 77 ThreeChannels imgHSI; 78 InitThreeChannels(imgHSI, w, h); 79 RGB2HSI(imgRGB, w, h, imgHSI); 80 81 // double min, max; 82 // GetMinMaxDouble(imgHSI.channel1, w*h, min, max); 83 // printf("%lf %lf\n", min, max); 84 85 // HSI转为RGB 86 ThreeChannels imgRGBtmp; 87 InitThreeChannels(imgRGBtmp, w, h); 88 HSI2RGB(imgHSI, w, h, imgRGBtmp); 89 90 // 打印最终结果 91 PrintRGBImage(imgRGBtmp, w, h); 92 93 getch(); 94 FreeThreeChannels(imgRGB); 95 FreeThreeChannels(imgHSI); 96 FreeThreeChannels(imgRGBtmp); 97 closegraph(); 98 return 0; 99 } 100 101 102 103 /* 在整型数组中找到最小值和最大值 */ 104 void GetMinMaxInt(int *arr, int n, int &min, int &max) { 105 min = 0x7fffffff; 106 max = 0x80000000; 107 for(int i=0; i<n; i++) { 108 if(arr[i] > max) max = arr[i]; 109 if(arr[i] < min) min = arr[i]; 110 } 111 } 112 /* 在浮点型数组中找到最小值和最大值 */ 113 void GetMinMaxDouble(double *arr, int n, double &min, double &max) { 114 min = 1.7976931348623158e+308; 115 max = 2.2250738585072014e-308; 116 for(int i=0; i<n; i++) { 117 if(arr[i] > max) max = arr[i]; 118 if(arr[i] < min) min = arr[i]; 119 } 120 } 121 122 123 /* 打印RGB彩色图像 */ 124 void PrintRGBImage(ThreeChannels &tc, int w, int h) { 125 color_t color; 126 int i, j, red, green, blue; 127 for(i=0; i<w; i++) { 128 for(j=0; j<h; j++) { 129 red = *(tc.channel1+h*i+j) * 255.0; 130 green = *(tc.channel2+h*i+j) * 255.0; 131 blue = *(tc.channel3+h*i+j) * 255.0; 132 color = EGERGB(red, green, blue); 133 putpixel(i, j, color); 134 } 135 } 136 } 137 /* 根据文件名获取RGB彩色图像 */ 138 void GetImageRGB(char *file, ThreeChannels &tc, int w, int h, int mode) { 139 color_t color; 140 int i, j, red, green, blue; 141 PIMAGE pimg = newimage(); 142 getimage(pimg, file, w, h); 143 144 for(i=0; i<w; i++) { 145 for(j=0; j<h; j++) { 146 color = getpixel(i, j, pimg); 147 red = EGEGET_R(color); 148 green = EGEGET_G(color); 149 blue = EGEGET_B(color); 150 *(tc.channel1+h*i+j) = red / 255.0; 151 *(tc.channel2+h*i+j) = green / 255.0; 152 *(tc.channel3+h*i+j) = blue / 255.0; 153 } 154 } 155 // 是否打印RGB彩色图像 156 if(mode) { 157 PrintRGBImage(tc, w, h); 158 } 159 delimage(pimg); 160 } 161 /* RGB转为HSI */ 162 void RGB2HSI(ThreeChannels &rgb, int w, int h, ThreeChannels &hsi) { 163 double rr, gg, bb, theta, ii, ss, hh, min_r_g_b; 164 int i, j; 165 for(i=0; i<w; i++) { 166 for(j=0; j<h; j++) { 167 rr = *(rgb.channel1+h*i+j); 168 gg = *(rgb.channel2+h*i+j); 169 bb = *(rgb.channel3+h*i+j); 170 171 min_r_g_b = rr<gg ? rr:gg; 172 min_r_g_b = bb<min_r_g_b ? bb:min_r_g_b; 173 174 /* 175 这有个小细节,且很容易被忽略 176 不能通过rr==gg==bb来避免除零的风险,这样仍然是错误的 177 而是如下这样 178 */ 179 if(rr==gg && rr==bb) theta=PI/2.0; 180 else theta = acos(0.5 * ((rr-gg)+(rr-bb)) / sqrt((rr-gg)*(rr-gg) + (rr-bb)*(gg-bb))); 181 hh = bb>gg ? (2.0*PI-theta):theta; 182 ii = 1.0/3.0 * (rr+gg+bb); 183 ss = 1.0 - min_r_g_b/ii; 184 185 *(hsi.channel1+h*i+j) = hh; 186 *(hsi.channel2+h*i+j) = ss; 187 *(hsi.channel3+h*i+j) = ii; 188 } 189 } 190 } 191 /* HSI转为RGB */ 192 void HSI2RGB(ThreeChannels &hsi, int w, int h, ThreeChannels &rgb) { 193 double ii, ss, hh, theta, rr, gg, bb; 194 int i, j; 195 196 for(i=0; i<w; i++) { 197 for(j=0; j<h; j++) { 198 hh = *(hsi.channel1+h*i+j); 199 ss = *(hsi.channel2+h*i+j); 200 ii = *(hsi.channel3+h*i+j); 201 202 if(hh>=0.0 && hh<(PI*120.0/180.0)) { 203 bb = ii * (1.0-ss); 204 rr = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh)); 205 gg = 3.0*ii - (rr+bb); 206 } else if(hh>=(PI*120.0/180.0) && hh<(PI*240.0/180.0)) { 207 hh -= PI*120.0/180.0; 208 rr = ii * (1.0-ss); 209 gg = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh)); 210 bb = 3.0*ii - (rr+gg); 211 } else if(hh>=(PI*240.0/180.0) && hh<(PI*360.0/180.0)) { 212 hh -= PI*240.0/180.0; 213 gg = ii * (1.0-ss); 214 bb = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh)); 215 rr = 3.0*ii - (gg+bb); 216 } 217 218 *(rgb.channel1+h*i+j) = rr; 219 *(rgb.channel2+h*i+j) = gg; 220 *(rgb.channel3+h*i+j) = bb; 221 } 222 } 223 }