Malvar-He-Cutler Linear Image Demosaicking
|
00001 00016 #include <string.h> 00017 #include <ctype.h> 00018 #include "imageio.h" 00019 00020 00021 typedef struct 00022 { 00023 uint32_t *Data; 00024 int Width; 00025 int Height; 00026 } image; 00027 00029 typedef struct 00030 { 00032 char *InputFile; 00034 char *OutputFile; 00036 int JpegQuality; 00038 int RedX; 00040 int RedY; 00042 int Flatten; 00044 int Padding; 00046 int ExtraRow; 00048 int ExtraColumn; 00050 int Verbose; 00051 } programparams; 00052 00053 00054 static int ParseParams(programparams *Param, int argc, char *argv[]); 00055 00056 00058 static void PrintHelpMessage() 00059 { 00060 printf("Image mosaicing utility, P. Getreuer 2010-2011\n\n"); 00061 printf("Usage: mosaic [options] <input file> <output file>\n\n" 00062 "Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n\n"); 00063 printf("Options:\n"); 00064 printf(" -p <pattern> CFA pattern, choices for <pattern> are\n"); 00065 printf(" RGGB upperleftmost red pixel is at (0,0)\n"); 00066 printf(" GRBG upperleftmost red pixel is at (1,0)\n"); 00067 printf(" GBRG upperleftmost red pixel is at (0,1)\n"); 00068 printf(" BGGR upperleftmost red pixel is at (1,1)\n\n"); 00069 printf(" -f Flatten result to a grayscale image\n"); 00070 printf(" -r Add one extra row to the top\n"); 00071 printf(" -c Add one extra column to the left\n"); 00072 printf(" -e <padding> Add <padding> pixels to each border of the image\n"); 00073 printf(" -v Verbose output\n\n"); 00074 #ifdef LIBJPEG_SUPPORT 00075 printf(" -q <number> Quality for saving JPEG images (0 to 100)\n\n"); 00076 #endif 00077 printf("Example: \n" 00078 " mosaic -v -p RGGB frog.bmp frog-m.bmp\n"); 00079 } 00080 00081 00088 static int WSymExtension(int N, int n) 00089 { 00090 while(1) 00091 { 00092 if(n < 0) 00093 n = -n; 00094 else if(n >= N) 00095 n = (2*N - 2) - n; 00096 else 00097 return n; 00098 } 00099 } 00100 00101 00102 int main(int argc, char *argv[]) 00103 { 00104 programparams Param; 00105 image u = {NULL, 0, 0}, f = {NULL, 0, 0}; 00106 uint32_t Pixel; 00107 int i, x, y, xOffset, yOffset, Green, Status = 1; 00108 int MaxShow = 2; 00109 char FillNext = ' '; 00110 00111 00112 if(!ParseParams(&Param, argc, argv)) 00113 return 0; 00114 00115 Green = 1 - ((Param.RedX + Param.RedY) & 1); 00116 00117 /* Read the input image */ 00118 if(!(u.Data = (uint32_t *)ReadImage(&u.Width, &u.Height, Param.InputFile, 00119 IMAGEIO_U8 | IMAGEIO_RGBA))) 00120 goto Catch; 00121 00122 f.Width = u.Width + 2*Param.Padding + Param.ExtraColumn; 00123 f.Height = u.Height + 2*Param.Padding + Param.ExtraRow; 00124 00125 if(!(f.Data = (uint32_t *)Malloc(sizeof(uint32_t)*f.Width*f.Height))) 00126 goto Catch; 00127 00128 xOffset = Param.Padding + Param.ExtraColumn; 00129 yOffset = Param.Padding + Param.ExtraRow; 00130 00131 if(Param.Verbose) 00132 printf("Resampling with pattern\n\n"); 00133 00134 /* Mosaic the image */ 00135 for(y = 0; y < f.Height; y++) 00136 for(x = 0; x < f.Width; x++) 00137 { 00138 Pixel = u.Data[WSymExtension(u.Width, x - xOffset) 00139 + u.Width*WSymExtension(u.Height, y - yOffset)]; 00140 00141 if(Param.Verbose && x <= xOffset + 2 && y <= yOffset + 2) 00142 { 00143 if((x < MaxShow || x >= xOffset) 00144 && (y < MaxShow || y >= yOffset)) 00145 { 00146 if(y == yOffset && x == xOffset) 00147 { 00148 printf("["); 00149 FillNext = ']'; 00150 } 00151 else 00152 { 00153 printf("%c", FillNext); 00154 FillNext = ' '; 00155 } 00156 00157 if(((x + y) & 1) == Green) 00158 printf("G"); 00159 else if((y & 1) == Param.RedY) 00160 printf("R"); 00161 else 00162 printf("B"); 00163 00164 if(x == xOffset + 2) 00165 { 00166 if(y == 0 || (yOffset > MaxShow && y == yOffset)) 00167 printf("..."); 00168 00169 printf("\n"); 00170 00171 if(y == MaxShow - 1 && yOffset > MaxShow) 00172 { 00173 if(xOffset <= MaxShow) 00174 i = xOffset + 3; 00175 else 00176 i = MaxShow + 4; 00177 00178 while(i--) 00179 printf(" :"); 00180 00181 printf("\n"); 00182 } 00183 } 00184 00185 00186 if(x == MaxShow - 1 && xOffset > MaxShow) 00187 { 00188 printf(".."); 00189 FillNext = '.'; 00190 } 00191 } 00192 } 00193 00194 if(!Param.Flatten) 00195 { 00196 if(((x + y) & 1) == Green) 00197 ((uint8_t *)&Pixel)[0] = ((uint8_t *)&Pixel)[2] = 0; 00198 else if((y & 1) == Param.RedY) 00199 ((uint8_t *)&Pixel)[1] = ((uint8_t *)&Pixel)[2] = 0; 00200 else 00201 ((uint8_t *)&Pixel)[0] = ((uint8_t *)&Pixel)[1] = 0; 00202 } 00203 else 00204 { 00205 if(((x + y) & 1) == Green) 00206 ((uint8_t *)&Pixel)[0] = 00207 ((uint8_t *)&Pixel)[2] = ((uint8_t *)&Pixel)[1]; 00208 else if((y & 1) == Param.RedY) 00209 ((uint8_t *)&Pixel)[1] = 00210 ((uint8_t *)&Pixel)[2] = ((uint8_t *)&Pixel)[0]; 00211 else 00212 ((uint8_t *)&Pixel)[0] = 00213 ((uint8_t *)&Pixel)[1] = ((uint8_t *)&Pixel)[2]; 00214 } 00215 00216 ((uint8_t *)&Pixel)[3] = 255; 00217 00218 f.Data[x + f.Width*y] = Pixel; 00219 } 00220 00221 if(Param.Verbose) 00222 { 00223 printf(" ... "); 00224 00225 if(xOffset > MaxShow) 00226 { 00227 i = MaxShow - 1; 00228 00229 while(i--) 00230 printf(" "); 00231 00232 printf("..."); 00233 } 00234 00235 printf("\n\n"); 00236 } 00237 00238 /* Write the output image */ 00239 if(!WriteImage(f.Data, f.Width, f.Height, Param.OutputFile, 00240 IMAGEIO_U8 | IMAGEIO_RGBA, Param.JpegQuality)) 00241 goto Catch; 00242 else if(Param.Verbose) 00243 printf("Output written to \"%s\".\n", Param.OutputFile); 00244 00245 Status = 0; 00246 Catch: 00247 Free(f.Data); 00248 Free(u.Data); 00249 return Status; 00250 } 00251 00252 00253 static int ParseParams(programparams *Param, int argc, char *argv[]) 00254 { 00255 static char *DefaultOutputFile = (char *)"out.bmp"; 00256 char *OptionString; 00257 char OptionChar; 00258 int i; 00259 00260 00261 if(argc < 2) 00262 { 00263 PrintHelpMessage(); 00264 return 0; 00265 } 00266 00267 /* Set parameter defaults */ 00268 Param->InputFile = 0; 00269 Param->OutputFile = DefaultOutputFile; 00270 Param->JpegQuality = 100; 00271 Param->RedX = 0; 00272 Param->RedY = 0; 00273 Param->Flatten = 0; 00274 Param->Padding = 0; 00275 Param->ExtraRow = 0; 00276 Param->ExtraColumn = 0; 00277 Param->Verbose = 0; 00278 00279 for(i = 1; i < argc;) 00280 { 00281 if(argv[i] && argv[i][0] == '-') 00282 { 00283 if((OptionChar = argv[i][1]) == 0) 00284 { 00285 ErrorMessage("Invalid parameter format.\n"); 00286 return 0; 00287 } 00288 00289 if(argv[i][2]) 00290 OptionString = &argv[i][2]; 00291 else if(++i < argc) 00292 OptionString = argv[i]; 00293 else 00294 { 00295 ErrorMessage("Invalid parameter format.\n"); 00296 return 0; 00297 } 00298 00299 switch(OptionChar) 00300 { 00301 case 'p': 00302 if(!strcmp(OptionString, "RGGB") 00303 || !strcmp(OptionString, "rggb")) 00304 { 00305 Param->RedX = 0; 00306 Param->RedY = 0; 00307 } 00308 else if(!strcmp(OptionString, "GRBG") 00309 || !strcmp(OptionString, "grbg")) 00310 { 00311 Param->RedX = 1; 00312 Param->RedY = 0; 00313 } 00314 else if(!strcmp(OptionString, "GBRG") 00315 || !strcmp(OptionString, "gbrg")) 00316 { 00317 Param->RedX = 0; 00318 Param->RedY = 1; 00319 } 00320 else if(!strcmp(OptionString, "BGGR") 00321 || !strcmp(OptionString, "bggr")) 00322 { 00323 Param->RedX = 1; 00324 Param->RedY = 1; 00325 } 00326 else 00327 ErrorMessage("CFA pattern must be RGGB, GRBG, GBRG, or BGGR\n"); 00328 break; 00329 case 'f': 00330 Param->Flatten = 1; 00331 i--; 00332 break; 00333 case 'e': 00334 Param->Padding = atoi(OptionString); 00335 00336 if(Param->Padding < 0) 00337 { 00338 ErrorMessage("Padding must be nonnegative.\n"); 00339 return 0; 00340 } 00341 break; 00342 case 'r': 00343 Param->ExtraRow = 1; 00344 i--; 00345 break; 00346 case 'c': 00347 Param->ExtraColumn = 1; 00348 i--; 00349 break; 00350 case 'v': 00351 Param->Verbose = 1; 00352 i--; 00353 break; 00354 00355 #ifdef LIBJPEG_SUPPORT 00356 case 'q': 00357 Param->JpegQuality = atoi(OptionString); 00358 00359 if(Param->JpegQuality <= 0 || Param->JpegQuality > 100) 00360 { 00361 ErrorMessage("JPEG quality must be between 0 and 100.\n"); 00362 return 0; 00363 } 00364 break; 00365 #endif 00366 case '-': 00367 PrintHelpMessage(); 00368 return 0; 00369 default: 00370 if(isprint(OptionChar)) 00371 ErrorMessage("Unknown option \"-%c\".\n", OptionChar); 00372 else 00373 ErrorMessage("Unknown option.\n"); 00374 00375 return 0; 00376 } 00377 00378 i++; 00379 } 00380 else 00381 { 00382 if(!Param->InputFile) 00383 Param->InputFile = argv[i]; 00384 else 00385 Param->OutputFile = argv[i]; 00386 00387 i++; 00388 } 00389 } 00390 00391 if(!Param->InputFile) 00392 { 00393 PrintHelpMessage(); 00394 return 0; 00395 } 00396 00397 if(!Param->Verbose) 00398 return 1; 00399 00400 00401 return 1; 00402 }