Malvar-He-Cutler Linear Image Demosaicking

mosaic.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines