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