libopenraw
bimedian_demosaic.cpp
00001 /* 
00002  * libopenraw - demoisaic.cpp
00003  *
00004  * This library is free software: you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public License
00006  * as published by the Free Software Foundation, either version 3 of
00007  * the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library.  If not, see
00016  * <http://www.gnu.org/licenses/>.
00017  *
00018  * This code has been adapted from GEGL:
00019  * Copyright 2006 Øyvind Kolås <pippin@gimp.org>
00020  * Copyright 2008 Bradley Broom <bmbroom@gmail.com>
00021  *
00022  * In libopenraw:
00023  * Copyright 2008-2009 Hubert Figuiere <hub@figuiere.net>
00024  * Copyright 2008 Novell Inc.
00025  */
00026 
00027 #include <stdlib.h>
00028 
00029 #include <algorithm>
00030 
00031 #include <libopenraw/demosaic.h>
00032 
00033 void bimedian_demosaic (uint16_t *src, uint32_t src_x, uint32_t src_y, 
00034                         or_cfa_pattern pattern, uint8_t *dst);
00035 
00036 /*
00037 extern "C" void or_demosaic(uint16_t*, uint32_t, uint32_t, or_cfa_pattern, uint8_t*)
00038 {
00039 }
00040 */
00041 
00042 /* Returns the median of four floats. We define the median as the average of
00043  * the central two elements.
00044  */
00045 static inline float
00046 m4 (float a, float b, float c, float d)
00047 {
00048     float t;
00049     
00050     /* Sort ab */
00051     if (a > b)
00052     {
00053         t = b;
00054         b = a;
00055         a = t;
00056     }
00057     /* Sort abc */
00058     if (b > c)
00059     {
00060         t = c;
00061         c = b;
00062         if (a > t)
00063         {
00064             b = a;
00065             a = t;
00066         }
00067         else
00068             b = t;
00069     }
00070     /* Return average of central two elements. */
00071     if (d >= c) /* Sorted order would be abcd */
00072         return (b + c) / 2.0;
00073     else if (d >= a) /* Sorted order would be either abdc or adbc */
00074         return (b + d) / 2.0;
00075     else /* Sorted order would be dabc */
00076         return (a + b) / 2.0;
00077 }
00078 
00079 /* Defines to make the row/col offsets below obvious. */
00080 #define ROW src_x
00081 #define COL 1
00082 
00083 /* We expect src_extent to have a one pixel border around all four sides
00084  * of dst_extent.
00085  */
00086 void
00087 bimedian_demosaic (uint16_t *src, uint32_t src_x, uint32_t src_y, 
00088              or_cfa_pattern pattern, uint8_t *dst)
00089 {
00090     uint32_t x,y;
00091     uint32_t offset, doffset;
00092     float *src_buf;
00093     float *dst_buf;
00094 
00095     int npattern = 0;
00096     switch(pattern) {
00097     case OR_CFA_PATTERN_GRBG:
00098         npattern = 0;
00099         break;
00100     case OR_CFA_PATTERN_BGGR:
00101         npattern = 1;
00102         break;
00103     case OR_CFA_PATTERN_GBRG:
00104         npattern = 2;
00105         break;
00106     case OR_CFA_PATTERN_RGGB:
00107         npattern = 3;
00108         break;
00109     default:
00110         break;
00111     }
00112     
00113     src_buf = (float*)calloc(src_x * src_y, sizeof(float));
00114     dst_buf = (float*)calloc(src_x * src_y * 3, sizeof(float));
00115 
00116     std::copy(src, src + (src_x * src_y), src_buf);
00117 
00118     offset = ROW + COL;
00119     doffset = 0;
00120     for(y = 1 ; y < src_y - 1; y++)
00121     {
00122         for (x = 1 ; x < src_x - 1; x++)
00123         {
00124             float red=0.0;
00125             float green=0.0;
00126             float blue=0.0;
00127             
00128             if ((y + npattern%2)%2==0) {
00129                 if ((x+npattern/2)%2==1) {
00130                     /* GRG
00131                      * BGB
00132                      * GRG
00133                      */
00134                     blue =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
00135                     green=src_buf[offset];
00136                     red  =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
00137                 }
00138                 else {
00139                     /* RGR
00140                      * GBG
00141                      * RGR
00142                      */
00143                     blue =src_buf[offset];
00144                     green=m4(src_buf[offset-ROW], src_buf[offset-COL],
00145                              src_buf[offset+COL], src_buf[offset+ROW]);
00146                     red  =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
00147                              src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
00148                 }
00149             }
00150             else {
00151                 if ((x+npattern/2)%2==1) {
00152                     /* BGB
00153                      * GRG
00154                      * BGB
00155                      */
00156                     blue =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
00157                              src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
00158                     green=m4(src_buf[offset-ROW], src_buf[offset-COL],
00159                              src_buf[offset+COL], src_buf[offset+ROW]);
00160                     red  =src_buf[offset];
00161                 }
00162                 else {
00163                     /* GBG
00164                      * RGR
00165                      * GBG
00166                      */
00167                     blue =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
00168                     green=src_buf[offset];
00169                     red  =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
00170                 }
00171             }
00172             
00173             dst_buf [doffset*3+0] = red / 16.0;
00174             dst_buf [doffset*3+1] = green / 16.0;
00175             dst_buf [doffset*3+2] = blue / 16.0;
00176             
00177             offset++;
00178             doffset++;
00179         }
00180         offset+=2;
00181     }
00182     std::copy(dst_buf, dst_buf + (src_x * src_y * 3), dst);     
00183     free(src_buf);
00184     free(dst_buf);
00185 }
00186 
00187 
00188 
00189 /*
00190   Local Variables:
00191   mode:c++
00192   c-file-style:"stroustrup"
00193   c-file-offsets:((innamespace . 0))
00194   indent-tabs-mode:nil
00195   fill-column:80
00196   End:
00197 */