00001 #include <math.h>
00002 #include <vector>
00003 #include <iostream>
00004 using namespace std;
00005
00006 #include "Demosaic.h"
00007 #include "../Sensor.h"
00008
00009
00010 namespace FCam {
00011 Image demosaic(Frame::Ptr frame, float gamma) {
00012 if (!frame || !frame->image.valid()) {
00013 cerr << "Cannot demosaic an invalid image" << endl;
00014 Image nullImage;
00015 return nullImage;
00016 }
00017
00018 cout << "Demosaicking" << endl;
00019
00020 int rawWidth = frame->image.size.width;
00021 int rawHeight = frame->image.size.height;
00022 Image out(rawWidth-4, rawHeight-4, RGB24);
00023
00024 int minVal = frame->sensor->minRawValue();
00025 int maxVal = frame->sensor->maxRawValue();
00026
00027
00028 vector<unsigned char> to8bit(maxVal+100);
00029 for (int i = 0; i < maxVal; i++) {
00030 float val = (i-minVal);
00031 if (val < 0) to8bit[i] = 0;
00032 else {
00033 val /= maxVal;
00034 if (val >= 1) to8bit[i] = 255;
00035 else {
00036 val = powf(val, 1.0f/gamma);
00037 to8bit[i] = (unsigned char)(val * 256 + 0.5);
00038 }
00039 }
00040 }
00041
00042
00043 int redX, redY;
00044 switch(frame->sensor->getBayerPattern()) {
00045 case Sensor::RGGB:
00046 redX = 0; redY = 0; break;
00047 case Sensor::BGGR:
00048 redX = 1; redY = 1; break;
00049 case Sensor::GBRG:
00050 redX = 0; redY = 1; break;
00051 case Sensor::GRBG:
00052 redX = 1; redY = 0; break;
00053 default:
00054 cerr << "Can't demosaic data from a non-bayer sensor." << endl;
00055 return out;
00056 }
00057
00058 unsigned char *outPtr = out.data;
00059 for (int y = 0; y < out.size.height; y++) {
00060 unsigned short *inPtr = ((unsigned short *)frame->image.data) + (y+2)*rawWidth + 2;
00061 for (int x = 0; x < out.size.width; x++) {
00062
00063 if ((y & 1) == redY) {
00064 if ((x & 1) == redX) {
00065
00066 *outPtr++ = to8bit[inPtr[0]];
00067 *outPtr++ = to8bit[(inPtr[-1] +
00068 inPtr[1] +
00069 inPtr[-rawWidth] +
00070 inPtr[rawWidth])>>2];
00071 *outPtr++ = to8bit[(inPtr[-1-rawWidth] +
00072 inPtr[1+rawWidth] +
00073 inPtr[1-rawWidth] +
00074 inPtr[-1+rawWidth])>>2];
00075 } else {
00076
00077 *outPtr++ = to8bit[(inPtr[-1] + inPtr[1])>>1];
00078 *outPtr++ = to8bit[inPtr[0]];
00079 *outPtr++ = to8bit[(inPtr[-rawWidth] + inPtr[rawWidth])>>1];
00080 }
00081 } else {
00082 if ((x & 1) == redX) {
00083
00084 *outPtr++ = to8bit[(inPtr[-rawWidth] + inPtr[rawWidth])>>1];
00085 *outPtr++ = to8bit[inPtr[0]];
00086 *outPtr++ = to8bit[(inPtr[-1] + inPtr[1])>>1];
00087 } else {
00088
00089 *outPtr++ = to8bit[(inPtr[-1-rawWidth] +
00090 inPtr[1+rawWidth] +
00091 inPtr[1-rawWidth] +
00092 inPtr[-1+rawWidth])>>2];
00093 *outPtr++ = to8bit[(inPtr[-1] +
00094 inPtr[1] +
00095 inPtr[-rawWidth] +
00096 inPtr[rawWidth])>>2];
00097 *outPtr++ = to8bit[inPtr[0]];
00098 }
00099 }
00100
00101 inPtr++;
00102 }
00103 }
00104
00105 cout << "Done demosaicking" << endl;
00106
00107 return out;
00108 }
00109 }