Advertisement
Guest User

Untitled

a guest
Apr 5th, 2017
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.20 KB | None | 0 0
  1. /*
  2.  * Copyright 2011 Juan Gabriel Gomila Salas <joan-by@hotmail.com>
  3.  *
  4.  * All rights reserved.
  5.  *
  6.  *
  7.  * Patent warning:
  8.  *
  9.  * This file implement one algorithm possibly linked to the patent
  10.  *
  11.  * # N. Moroney, R.G. Beausoleil and I. Sobel, Local Color Correction,
  12.  * US Patent 6,822,762, (November 23, 2004)
  13.  *
  14.  * This file is made available for the exclusive aim of serving as
  15.  * scientific tool to verify the soundness and completeness of the
  16.  * algorithm description. Compilation, execution and redistribution
  17.  * of this file may violate patents rights in certain countries.
  18.  * The situation being different for every country and changing
  19.  * over time, it is your responsibility to determine which patent
  20.  * rights restrictions apply to you before you compile, use,
  21.  * modify, or redistribute this file. A patent lawyer is qualified
  22.  * to make this determination.
  23.  * If and only if they don't conflict with any patent terms, you
  24.  * can benefit from the following license terms attached to this
  25.  * file.
  26.  *
  27.  * License:
  28.  *
  29.  * This program is provided for scientific and educational only:
  30.  * you can use and/or modify it for these purposes, but you are
  31.  * not allowed to redistribute this work or derivative works in
  32.  * source or executable form. A license must be obtained from the
  33.  * patent right holders for any other use.
  34.  *
  35.  *
  36.  */
  37.  
  38. /**
  39.  * @file localcolorcorrection.c
  40.  * @brief Local Color Correction algorithm
  41.  *
  42.  * Parameters:
  43.  *
  44.  * input image
  45.  * output image
  46.  *
  47.  * Read/write operations (png format) make use
  48.  * of io_png.c and io_png.h, by Nicolas Limare
  49.  *
  50.  * Conversion operations between color spaces, make use
  51.  * colorspace library, by Pascal Getreuer
  52.  *
  53.  * @author Juan Gabriel Gomila Salas <joan-by@hotmail.com>
  54.  *
  55.  */
  56.  
  57. /**
  58.  * @mainpage Local Color Correction
  59.  *
  60.  * README.txt:
  61.  * @verbinclude README.txt
  62.  */
  63.  
  64. /**
  65.  * @file   localcolorcorrection.c
  66.  * @brief  Main executable file
  67.  *
  68.  *
  69.  * @author Juan Gabriel Gomila Salas <joan-by@hotmail.com>
  70.  */
  71.  
  72. #include <stdio.h>
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include <math.h>
  76. #include "structs.h"
  77. #include "io_png.h"
  78. #include <limits.h>
  79. #include <xmmintrin.h>  // SSE
  80. #include <pmmintrin.h>  // SSE
  81. #include <assert.h>
  82. #include <omp.h>
  83.  
  84.  
  85. /**
  86.  * @brief main function call
  87.  */
  88. void *contrast_enhance ( pixel *input, int w, int h )
  89. {
  90.     int   radius, n, nx, ny, t;
  91.     float *Mask, *Mask2, *Kernel;
  92.     float sum;
  93.  
  94.     pixel * output = (pixel *) malloc ( sizeof ( pixel ) * w * h );
  95.     radius = 40;
  96.  
  97.     //I     = (float *) malloc ( w * h * sizeof ( float ) );
  98.     Mask  = (float *) malloc ( w * h * sizeof ( float ) );
  99.     Mask2 = (float *) malloc ( w * h * sizeof ( float ) );
  100.     /*Create convolution kernel*/
  101.     Kernel = (float *) malloc ( ( 2 * radius + 1 ) * sizeof ( float ) );
  102. /*
  103.     for ( n = 0; n < w * h; n++ ) {
  104.         I[n] = ( ( input[n].R / 255.0 ) + ( input[n].G / 255.0 ) + ( input[n].B / 255.0 ) ) / 3.0f;
  105.     }
  106.  
  107.     for ( n = 0; n < w * h; n++ ) {
  108.         Mask[n]  = I[n];
  109.         Mask2[n] = Mask[n];
  110.     }*/
  111.  
  112.     /*#pragma omp parallel private(step,start,cpu,stop) shared(w,h,input,Mask,Mask2)
  113.     {
  114.       //step = (w*h) / omp_get_num_threads ();
  115.       //cpu = omp_get_thread_num ();
  116.       //stop = min ( ( cpu + 1 ) * step, (w*h));
  117.       //start = cpu * step;
  118.       #pragma omp for private(n)
  119.       for ( n = 0; n < w*h; n++) {
  120.         Mask[n] = ( ( input[n].R / 255.0 ) + ( input[n].G / 255.0 ) + ( input[n].B / 255.0 ) ) / 3.0f;
  121.         Mask2[n]  = Mask[n];
  122.     }
  123.   }*/
  124.   #pragma omp parallel for private(n) shared(w,h,input,Mask,Mask2)
  125.     for ( n = 0; n < w*h; n++) {
  126.       Mask[n] = ( ( input[n].R / 255.0 ) + ( input[n].G / 255.0 ) + ( input[n].B / 255.0 ) ) / 3.0f;
  127.       Mask2[n]  = Mask[n];
  128.   }
  129.  
  130.  
  131.  
  132.     if ( radius > 0 ) {
  133.         #pragma omp parallel for default(none) private(n) shared(radius, Kernel)
  134.         for ( n = 0; n < 2 * radius + 1; n++ ) {
  135.             Kernel[n] =
  136.                 (float) exp ( (double) ( -2.0f * ( -radius + n ) * ( -radius + n ) / ( radius * radius ) ) );
  137.         }
  138.  
  139.         sum = 0.0f;
  140.         //#pragma omp parallel for default(none) private(n) shared(radius, Kernel)
  141.         for ( n = 0; n < 2 * radius + 1; n++ ) {
  142.             //#pragma omp atomic
  143.                    sum = sum + Kernel[n];
  144.         }
  145.         #pragma omp parallel for default(none) private(n) shared(radius, Kernel, sum)
  146.         for ( n = 0; n < 2 * radius + 1; n++ ) {
  147.             Kernel[n] = (float) ( Kernel[n] / sum );
  148.         }
  149.  
  150.         /*If the radius of the mask is less than the mid-size of the image,
  151.            we perform the desired algorithm*/
  152.         if ( radius < w / 2 && radius < h / 2 ) {
  153.           /*Convolve in the x direction*/
  154.         /*  #pragma omp parallel for default(none) shared(radius,w,h,Mask,Kernel,Mask2) private(ny,t, sum)
  155.             for ( nx = 0; nx < w; nx++ ) {
  156.                 for ( ny = 0; ny < h; ny++ ) {
  157.                     sum = 0.0f;
  158.                     for ( t = -radius; t <= radius; t++ ) {
  159.                         if ( nx + t >= w ) {
  160.                             sum = sum + Mask[2 * w - 2 - nx - t + ny * w] * Kernel[t + radius];
  161.                         }
  162.                         else{
  163.                             sum = sum + Mask[abs ( nx + t ) + ny * w] * Kernel[t + radius];
  164.                         }
  165.                     }
  166.                     Mask2[nx + ny * w] = (float) sum;
  167.                 }
  168.             }*/
  169.  
  170. /*
  171.     //WITHOUT ABS()
  172.  #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
  173.  #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
  174.      int limit, limit2;
  175.      for ( nx = 0; nx < w; nx++ ) {
  176.          for ( ny = 0; ny < h; ny++ ) {
  177.              sum = 0.0f;
  178.              for ( t = w-nx; t <= radius; t++ ) {
  179.                 sum = sum + Mask[2 * w - 2 - nx - t + ny * w] * Kernel[t + radius];
  180.              }
  181.              limit2 = MAX(-nx, -radius-1);
  182.              for ( t = -radius; t <= limit2; t++ ) {
  183.                  sum = sum + Mask[ -(nx + t ) + ny * w] * Kernel[t + radius];
  184.              }
  185.              limit = MIN(w-nx-1, radius);
  186.              for ( t = limit2+1; t <= limit; t++ ) {
  187.                  sum = sum + Mask[( nx + t ) + ny * w] * Kernel[t + radius];
  188.              }
  189.              Mask2[nx + ny * w] = (float) sum;
  190.          }
  191.      }
  192. */
  193.      //WITH OpenMP
  194.      #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
  195.      #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
  196.      int limit, limit2;
  197.      #pragma omp parallel for private(t, ny, limit, limit2, sum) shared(w,h,Mask,Mask2,Kernel, radius)
  198.      for ( nx = 0; nx < w; nx++ ) {
  199.        for ( ny = 0; ny < h; ny++ ) {
  200.          sum = 0.0f;
  201.          for ( t = w-nx; t <= radius; t++ ) {
  202.            sum = sum + Mask[2 * w - 2 - nx - t + ny * w] * Kernel[t + radius];
  203.          }
  204.          limit2 = MAX(-nx, -radius-1);
  205.          for ( t = -radius; t <= limit2; t++ ) {
  206.            sum = sum + Mask[ -(nx + t ) + ny * w] * Kernel[t + radius];
  207.          }
  208.          limit = MIN(w-nx-1, radius);
  209.          for ( t = limit2+1; t <= limit; t++ ) {
  210.            sum = sum + Mask[( nx + t ) + ny * w] * Kernel[t + radius];
  211.          }
  212.          Mask2[nx + ny * w] = (float) sum;
  213.        }
  214.      }
  215.  
  216.  
  217.  
  218. /*#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
  219. #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
  220. int limit, limit2;
  221. #pragma omp parallel for default(none) shared(w) private(nx)
  222. for ( nx = 0; nx < w; nx++ ) {
  223.   #pragma omp parallel for default(none) shared(h, w, radius, Mask2, nx) private(ny, sum, limit, limit2)
  224.   for ( ny = 0; ny < h; ny++ ) {
  225.     sum = 0.0f;
  226.     #pragma omp parallel for reduction(+:sum) default(none) shared(radius, nx, ny, Mask, Kernel, w) private(t)
  227.     for ( t = w-nx; t <= radius; t++ ) {
  228.       sum = sum + Mask[2 * w - 2 - nx - t + ny * w] * Kernel[t + radius];
  229.     }
  230.     limit2 = MAX(-nx, -radius-1);
  231.     #pragma omp parallel for reduction(+:sum) default(none) shared(radius, nx, ny, Mask, Kernel, limit2, w) private(t)
  232.     for ( t = -radius; t <= limit2; t++ ) {
  233.       sum = sum + Mask[ -(nx + t ) + ny * w] * Kernel[t + radius];
  234.     }
  235.     limit = MIN(w-nx-1, radius);
  236.     #pragma omp parallel for reduction(+:sum) default(none) shared(radius, nx, ny, Mask, Kernel, limit2, limit, w) private(t)
  237.     for ( t = limit2+1; t <= limit; t++ ) {
  238.       sum = sum + Mask[( nx + t ) + ny * w] * Kernel[t + radius];
  239.     }
  240.     Mask2[nx + ny * w] = (float) sum;
  241.   }
  242. }/*
  243.             /*Convolve in the y direction*/
  244.             /*#pragma omp parallel for default(none) shared(radius,w,h,Mask,Kernel,Mask2) private(nx,t, sum)
  245.             for ( ny = 0; ny < h; ny++ ) {
  246.                 for ( nx = 0; nx < w; nx++ ) {
  247.                     sum = 0.0f;
  248.                     for ( t = -radius; t <= radius; t++ ) {
  249.                         if ( ny + t >= h ) {
  250.                             sum = sum + Mask2[nx + ( 2 * h - 2 - ny - t ) * w] *
  251.                                   Kernel[t + radius];
  252.                         }
  253.                         else{
  254.                             sum = sum + Mask2[nx + abs ( ny + t ) * w] *
  255.                                   Kernel[t + radius];
  256.                         }
  257.                     }
  258.                     Mask[nx + ny * w] = (float) sum;
  259.                 }
  260.             }*/
  261.             #pragma omp parallel for default(none) private(t, nx, limit, limit2, sum) shared(w,h,Mask,Mask2,Kernel, radius)
  262.             for ( ny = 0; ny < h; ny++ ) {
  263.                 for ( nx = 0; nx < w; nx++ ) {
  264.                     sum = 0.0f;
  265.                     for ( t = h-ny; t <= radius; t++ ) {
  266.                       sum = sum + Mask2[nx + ( 2 * h - 2 - ny - t ) * w] * Kernel[t + radius];
  267.                     }
  268.                     limit2 = MAX(-ny, -radius-1);
  269.                     for ( t = -radius; t <= limit2; t++ ) {
  270.                       sum = sum + Mask2[nx - ( ny + t ) * w] * Kernel[t + radius];
  271.                     }
  272.                     limit = MIN(h-ny-1, radius);
  273.                     for ( t = limit2+1; t <= limit; t++ ){
  274.                       sum = sum + Mask2[nx + ( ny + t ) * w] * Kernel[t + radius];
  275.                     }
  276.                     Mask[nx + ny * w] = (float) sum;
  277.                 }
  278.             }
  279.         }
  280.         else {
  281.             /*Otherwise, perform a simple gamma correction*/
  282.             //#pragma omp parallel for default(none) private(nx) shared(Mask, h, w) reduction(+:sum)
  283.             for ( ny = 0; ny < h; ny++ ) {
  284.                 for ( nx = 0; nx < w; nx++ ) {
  285.                     sum = sum + Mask[nx + ny * w];
  286.                 }
  287.             }
  288.             sum = sum / ( w * h );
  289.             for ( ny = 0; ny < h; ny++ ) {
  290.                 for ( nx = 0; nx < w; nx++ ) {
  291.                     Mask[nx + ny * w] = sum;
  292.                 }
  293.             }
  294.         }
  295.     }
  296.  
  297.     #pragma omp parallel for default(none) private(n) shared(Mask, output, input, h, w)
  298.     for ( n = 0; n < w * h; n++ ) {
  299.         Mask[n] = (float) ( 2 * Mask[n] - 1 );
  300.         Mask[n] = (float) pow ( 2.0, (double) Mask[n] );
  301.  
  302.         output[n].R = min ( 255, 255 * (float) pow ( (double) input[n].R / 255.0, (double) Mask[n] ) );
  303.         output[n].G = min ( 255, 255 * (float) pow ( (double) ( input[n].G / 255.0 ), (double) Mask[n] ) );
  304.         output[n].B = min ( 255, 255 * (float) pow ( (double) ( input[n].B / 255.0 ), (double) Mask[n] ) );
  305.     }
  306.  
  307.     //free ( I );
  308.     free ( Mask );
  309.     free ( Mask2 );
  310.     free ( Kernel );
  311.  
  312.     return output;
  313. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement