libopenraw
|
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 */