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 /*
00034 extern "C" void or_demosaic(uint16_t*, uint32_t, uint32_t, or_cfa_pattern, uint8_t*)
00035 {
00036 }
00037 */
00038 
00039 /* Returns the median of four floats. We define the median as the average of
00040  * the central two elements.
00041  */
00042 static inline float
00043 m4 (float a, float b, float c, float d)
00044 {
00045     float t;
00046     
00047     /* Sort ab */
00048     if (a > b)
00049     {
00050         t = b;
00051         b = a;
00052         a = t;
00053     }
00054     /* Sort abc */
00055     if (b > c)
00056     {
00057         t = c;
00058         c = b;
00059         if (a > t)
00060         {
00061             b = a;
00062             a = t;
00063         }
00064         else
00065             b = t;
00066     }
00067     /* Return average of central two elements. */
00068     if (d >= c) /* Sorted order would be abcd */
00069         return (b + c) / 2.0;
00070     else if (d >= a) /* Sorted order would be either abdc or adbc */
00071         return (b + d) / 2.0;
00072     else /* Sorted order would be dabc */
00073         return (a + b) / 2.0;
00074 }
00075 
00076 /* Defines to make the row/col offsets below obvious. */
00077 #define ROW src_x
00078 #define COL 1
00079 
00080 /* We expect src_extent to have a one pixel border around all four sides
00081  * of dst_extent.
00082  */
00083 void
00084 bimedian_demosaic (uint16_t *src, uint32_t src_x, uint32_t src_y, 
00085              or_cfa_pattern pattern, uint8_t *dst)
00086 {
00087     uint32_t x,y;
00088     uint32_t offset, doffset;
00089     float *src_buf;
00090     float *dst_buf;
00091 
00092     int npattern = 0;
00093     switch(pattern) {
00094     case OR_CFA_PATTERN_GRBG:
00095         npattern = 0;
00096         break;
00097     case OR_CFA_PATTERN_BGGR:
00098         npattern = 1;
00099         break;
00100     case OR_CFA_PATTERN_GBRG:
00101         npattern = 2;
00102         break;
00103     case OR_CFA_PATTERN_RGGB:
00104         npattern = 3;
00105         break;
00106     default:
00107         break;
00108     }
00109     
00110     src_buf = (float*)calloc(src_x * src_y, sizeof(float));
00111     dst_buf = (float*)calloc(src_x * src_y * 3, sizeof(float));
00112 
00113     std::copy(src, src + (src_x * src_y), src_buf);
00114 
00115     offset = ROW + COL;
00116     doffset = 0;
00117     for(y = 1 ; y < src_y - 1; y++)
00118     {
00119         for (x = 1 ; x < src_x - 1; x++)
00120         {
00121             float red=0.0;
00122             float green=0.0;
00123             float blue=0.0;
00124             
00125             if ((y + npattern%2)%2==0) {
00126                 if ((x+npattern/2)%2==1) {
00127                     /* GRG
00128                      * BGB
00129                      * GRG
00130                      */
00131                     blue =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
00132                     green=src_buf[offset];
00133                     red  =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
00134                 }
00135                 else {
00136                     /* RGR
00137                      * GBG
00138                      * RGR
00139                      */
00140                     blue =src_buf[offset];
00141                     green=m4(src_buf[offset-ROW], src_buf[offset-COL],
00142                              src_buf[offset+COL], src_buf[offset+ROW]);
00143                     red  =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
00144                              src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
00145                 }
00146             }
00147             else {
00148                 if ((x+npattern/2)%2==1) {
00149                     /* BGB
00150                      * GRG
00151                      * BGB
00152                      */
00153                     blue =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
00154                              src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
00155                     green=m4(src_buf[offset-ROW], src_buf[offset-COL],
00156                              src_buf[offset+COL], src_buf[offset+ROW]);
00157                     red  =src_buf[offset];
00158                 }
00159                 else {
00160                     /* GBG
00161                      * RGR
00162                      * GBG
00163                      */
00164                     blue =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
00165                     green=src_buf[offset];
00166                     red  =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
00167                 }
00168             }
00169             
00170             dst_buf [doffset*3+0] = red / 16.0;
00171             dst_buf [doffset*3+1] = green / 16.0;
00172             dst_buf [doffset*3+2] = blue / 16.0;
00173             
00174             offset++;
00175             doffset++;
00176         }
00177         offset+=2;
00178     }
00179     std::copy(dst_buf, dst_buf + (src_x * src_y * 3), dst);     
00180     free(src_buf);
00181     free(dst_buf);
00182 }
00183 
00184 
00185 
00186 /*
00187   Local Variables:
00188   mode:c++
00189   c-file-style:"stroustrup"
00190   c-file-offsets:((innamespace . 0))
00191   indent-tabs-mode:nil
00192   fill-column:80
00193   End:
00194 */

Generated on Wed Aug 25 01:26:34 2010 for libopenraw by  doxygen 1.5.9