Author: post
Date: 2009-09-20 19:56:12 +0200 (Sun, 20 Sep 2009)
New Revision: 2635

Modified:
   trunk/plugins/demosaic/demosaic.c
Log:
Added conservative hotpixel removal. Added better threading for Pixelgrouping 
demosaic, by threading unpack and border interpolation.

Modified: trunk/plugins/demosaic/demosaic.c
===================================================================
--- trunk/plugins/demosaic/demosaic.c   2009-09-20 14:30:04 UTC (rev 2634)
+++ trunk/plugins/demosaic/demosaic.c   2009-09-20 17:56:12 UTC (rev 2635)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2009 Anders Brander <[email protected]> and 
+ * Copyright (C) 2006-2009 Anders Brander <[email protected]> and
  * Anders Kvist <[email protected]>
  *
  * This program is free software; you can redistribute it and/or
@@ -31,7 +31,7 @@
        gint start_y;
        gint end_y;
        RS_IMAGE16 *image;
-       RS_IMAGE16 *none_out; /* Used by "none" */
+       RS_IMAGE16 *output;
        guint filters;
        GThread *threadid;
 } ThreadInfo;
@@ -73,11 +73,14 @@
 static void set_property (GObject *object, guint property_id, const GValue 
*value, GParamSpec *pspec);
 static RSFilterResponse *get_image(RSFilter *filter, const RSFilterParam 
*param);
 static inline int fc_INDI (const unsigned int filters, const int row, const 
int col);
-static void border_interpolate_INDI (RS_IMAGE16 *image, const unsigned int 
filters, int colors, int border);
-static void lin_interpolate_INDI(RS_IMAGE16 *image, const unsigned int 
filters, const int colors);
-static void ppg_interpolate_INDI(RS_IMAGE16 *image, const unsigned int 
filters, const int colors);
+static void border_interpolate_INDI (const ThreadInfo* t, int colors, int 
border);
+static void lin_interpolate_INDI(RS_IMAGE16 *image, RS_IMAGE16 *output, const 
unsigned int filters, const int colors);
+static void ppg_interpolate_INDI(RS_IMAGE16 *image, RS_IMAGE16 *output, const 
unsigned int filters, const int colors);
 static void none_interpolate_INDI(RS_IMAGE16 *in, RS_IMAGE16 *out, const 
unsigned int filters, const int colors);
+static void hotpixel_detect(const ThreadInfo* t);
+static void expand_cfa_data(const ThreadInfo* t);
 
+
 static RSFilterClass *rs_demosaic_parent_class = NULL;
 
 G_MODULE_EXPORT void
@@ -167,10 +170,7 @@
        RSFilterResponse *response;
        RS_IMAGE16 *input;
        RS_IMAGE16 *output = NULL;
-       gint row, col;
        guint filters;
-       gushort *src;
-       gushort *dest;
        RS_DEMOSAIC method;
 
        previous_response = rs_filter_get_image(filter->previous, param);
@@ -203,42 +203,25 @@
                rs_filter_response_set_quick(response);
        }
 
-
        /* Magic - Ask Dave ;) */
        filters = input->filters;
        filters &= ~((filters & 0x55555555) << 1);
 
        /* Check if pattern is 2x2, otherwise we cannot do "none" demosaic */
-       if (method == RS_DEMOSAIC_NONE) 
+       if (method == RS_DEMOSAIC_NONE)
                if (! ( (filters & 0xff ) == ((filters >> 8) & 0xff) &&
                        ((filters >> 16) & 0xff) == ((filters >> 24) & 0xff) &&
                        (filters & 0xff) == ((filters >> 24) &0xff)))
                                method = RS_DEMOSAIC_PPG;
 
 
-       /* Populate new image with bayer data */
-  if (method != RS_DEMOSAIC_NONE) 
-       {
-               for(row=0; row<output->h; row++)
-               {
-                       src = GET_PIXEL(input, 0, row);
-                       dest = GET_PIXEL(output, 0, row);
-                       for(col=0;col<output->w;col++)
-                       {
-                               dest[fc_INDI(filters, row, col)] = *src;
-                               dest += output->pixelsize;
-                               src++;
-                       }
-               }
-       }
-
        switch (method)
        {
          case RS_DEMOSAIC_BILINEAR:
-                       lin_interpolate_INDI(output, filters, 3);
+                       lin_interpolate_INDI(input, output, filters, 3);
                        break;
          case RS_DEMOSAIC_PPG:
-                       ppg_interpolate_INDI(output, filters, 3);
+                       ppg_interpolate_INDI(input,output, filters, 3);
                        break;
                case RS_DEMOSAIC_NONE:
                        none_interpolate_INDI(input, output, filters, 3);
@@ -247,7 +230,7 @@
                        /* Do nothing */
                        break;
                }
-  
+
        g_object_unref(input);
        return response;
 }
@@ -292,19 +275,21 @@
 
 
 static void
-border_interpolate_INDI (RS_IMAGE16 *image, const unsigned int filters, int 
colors, int border)
+border_interpolate_INDI (const ThreadInfo* t, int colors, int border)
 {
        int row, col, y, x, f, c, sum[8];
+       RS_IMAGE16* image = t->output;
+       guint filters = t->filters;
 
-       for (row=0; row < image->h; row++) 
-               for (col=0; col < image->w; col++) 
+       for (row=t->start_y; row < t->end_y; row++)
+               for (col=0; col < image->w; col++)
                {
                        if (col==border && row >= border && row < 
image->h-border)
                                col = image->w-border;
                        memset (sum, 0, sizeof sum);
                        for (y=row-1; y != row+2; y++)
                                for (x=col-1; x != col+2; x++)
-                                       if (y >= 0 && y < image->h && x >= 0 && 
x < image->w) 
+                                       if (y >= 0 && y < image->h && x >= 0 && 
x < image->w)
                                        {
                                                f = FC(y, x);
                                                sum[f] += GET_PIXEL(image, x, 
y)[f];
@@ -318,13 +303,23 @@
 }
 
 static void
-lin_interpolate_INDI(RS_IMAGE16 *image, const unsigned int filters, const int 
colors) /*UF*/
+lin_interpolate_INDI(RS_IMAGE16 *input, RS_IMAGE16 *output, const unsigned int 
filters, const int colors) /*UF*/
 {
+       ThreadInfo *t = g_new(ThreadInfo, 1);
+       t->image = input;
+       t->output = output;
+       t->filters = filters;
+       t->start_y = 0;
+       t->end_y = input->w;
+
+       expand_cfa_data(t);
+       RS_IMAGE16* image = output;
+
   int code[16][16][32], *ip, sum[4];
   int c, i, x, y, row, col, shift, color;
   ushort *pix;
 
-  border_interpolate_INDI(image, filters, colors, 1);
+  border_interpolate_INDI(t, colors, 1);
   for (row=0; row < 16; row++)
     for (col=0; col < 16; col++) {
       ip = code[row][col];
@@ -357,6 +352,28 @@
     }
 }
 
+static void
+expand_cfa_data(const ThreadInfo* t) {
+
+       RS_IMAGE16* input  = t->image;
+       RS_IMAGE16* output = t->output;
+       guint filters = t->filters;
+       guint col, row;
+
+       /* Populate new image with bayer data */
+       for(row=t->start_y; row<t->end_y; row++)
+       {
+               gushort* src = GET_PIXEL(input, 0, row);
+               gushort* dest = GET_PIXEL(output, 0, row);
+               for(col=0;col<output->w;col++)
+               {
+                       dest[fc_INDI(filters, row, col)] = *src;
+                       dest += output->pixelsize;
+                       src++;
+               }
+       }
+}
+
 /*
    Patterned Pixel Grouping Interpolation by Alain Desbiolles
 */
@@ -368,7 +385,7 @@
 static void
 interpolate_INDI_part(ThreadInfo *t)
 {
-  RS_IMAGE16 *image = t->image;
+  RS_IMAGE16 *image = t->output;
   const unsigned int filters = t->filters;
   const int start_y = t->start_y;
   const int end_y = t->end_y;
@@ -433,7 +450,7 @@
                                ABS(pix[ d][1] - pix[0][1]);
                        guessB = pix[-d][c] + pix[d][c] + 2*pix[0][1]
                                - pix[-d][1] - pix[d][1];
-      
+
                        if (diffA > diffB)
                                pix[0][c] = CLIP(guessB >> 1);
                        else
@@ -446,7 +463,9 @@
 start_interp_thread(gpointer _thread_info)
 {
        ThreadInfo* t = _thread_info;
-
+       hotpixel_detect(t);
+       expand_cfa_data(t);
+       border_interpolate_INDI (t, 3, 3);
        interpolate_INDI_part(t);
        g_thread_exit(NULL);
 
@@ -454,14 +473,12 @@
 }
 
 static void
-ppg_interpolate_INDI(RS_IMAGE16 *image, const unsigned int filters, const int 
colors)
+ppg_interpolate_INDI(RS_IMAGE16 *image, RS_IMAGE16 *output, const unsigned int 
filters, const int colors)
 {
        guint i, y_offset, y_per_thread, threaded_h;
        const guint threads = rs_get_number_of_processor_cores();
        ThreadInfo *t = g_new(ThreadInfo, threads);
 
-       border_interpolate_INDI (image, filters, colors, 3);
-
        /* Subtract 3 from top and bottom  */
        threaded_h = image->h-6;
        y_per_thread = (threaded_h + threads-1)/threads;
@@ -470,6 +487,7 @@
        for (i = 0; i < threads; i++)
        {
                t[i].image = image;
+               t[i].output = output;
                t[i].filters = filters;
                t[i].start_y = y_offset;
                y_offset += y_per_thread;
@@ -494,28 +512,28 @@
        gushort *dest;
 
        ThreadInfo* t = _thread_info;
-       gint ops = t->none_out->pixelsize;
-       gint ors = t->none_out->rowstride;
+       gint ops = t->output->pixelsize;
+       gint ors = t->output->rowstride;
        guint filters = t->filters;
 
        for(row=t->start_y; row < t->end_y; row++)
        {
                src = GET_PIXEL(t->image, 0, row);
-               dest = GET_PIXEL(t->none_out, 0, row);
+               dest = GET_PIXEL(t->output, 0, row);
                guint first = FC(row, 0);
                guint second = FC(row, 1);
-               gint col_end = t->none_out->w - 2;
+               gint col_end = t->output->w - 2;
 
                if (first == 1) {  // Green first
                        for(col=0 ; col < col_end; col += 2)
                        {
                                dest[1] = dest[1+ops]= *src;
                                /* Move to next pixel */
-                               src++;   
+                               src++;
                                dest += ops;
 
-                               dest[second] = dest[second+ops] = 
-                               dest[second+ors] = dest[second+ops+ors] = *src; 
 
+                               dest[second] = dest[second+ops] =
+                               dest[second+ors] = dest[second+ops+ors] = *src;
 
                                /* Move to next pixel */
                                dest += ops;
@@ -524,8 +542,8 @@
                } else {
                        for(col=0 ; col < col_end; col += 2)
                        {
-                               dest[first] = dest[first+ops] = 
-                               dest[first+ors] = dest[first+ops+ors] = *src;  
+                               dest[first] = dest[first+ops] =
+                               dest[first+ors] = dest[first+ops+ors] = *src;
 
                                dest += ops;
                                src++;
@@ -559,7 +577,7 @@
                t[i].image = in;
                t[i].filters = filters;
                t[i].start_y = y_offset;
-               t[i].none_out = out;
+               t[i].output = out;
                y_offset += y_per_thread;
                y_offset = MIN(out->h-1, y_offset);
                t[i].end_y = y_offset;
@@ -573,3 +591,62 @@
 
        g_free(t);
 }
+
+static void
+hotpixel_detect(const ThreadInfo* t)
+{
+
+       RS_IMAGE16 *image = t->image;
+
+       gint x, y, end_y;
+       y = MAX( 4, t->start_y);
+       end_y = MIN(t->end_y, image->h - 4);
+
+       for(; y < end_y; y++)
+       {
+               gint col_end = image->w - 4;
+               gushort* img = GET_PIXEL(image, 0, y);
+               gint p = image->rowstride * 2;
+               for (x = 4; x < col_end ; x++) {
+                       /* Calculate minimum difference to surrounding pixels */
+                       gint left = (int)img[x - 2];
+                       gint c = (int)img[x];
+                       gint right = (int)img[x + 2];
+                       gint up = (int)img[x - p];
+                       gint down = (int)img[x + p];
+
+                       gint d = ABS(c - left);
+                       d = MIN(d, ABS(c - right));
+                       d = MIN(d, ABS(c - up));
+                       d = MIN(d, ABS(c - down));
+
+                       /* Also calculate maximum difference between 
surrounding pixels themselves */
+                       gint d2 = ABS(left - right);
+                       d2 = MAX(d2, ABS(up - down));
+
+                       /* If difference larger than surrounding pixels by a 
factor of 4,
+                               replace with left/right pixel interpolation */
+
+                       if ((d > d2 * 10) && (d > 2000)) {
+                               /* Do extended test! */
+                               left = (int)img[x - 4];
+                               right = (int)img[x + 4];
+                               up = (int)img[x - p * 2];
+                               down = (int)img[x + p * 2];
+
+                               d = MIN(d, ABS(c - left));
+                               d = MIN(d, ABS(c - right));
+                               d = MIN(d, ABS(c - up));
+                               d = MIN(d, ABS(c - down));
+
+                               d2 = MAX(d2, ABS(left - right));
+                               d2 = MAX(d2, ABS(up - down));
+
+                               if ((d > d2 * 10) && (d > 2000)) {
+                                       img[x] = (gushort)(((gint)img[x-2] + 
(gint)img[x+2] + 1) >> 1);
+                               }
+                       }
+
+               }
+       }
+}


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to