summaryrefslogtreecommitdiffstats
path: root/src/filter/equaliz0r/equaliz0r.cpp
blob: b4eae1ee48536d95714c5e42db7b078748a1d809 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* equaliz0r.cpp
 * Copyright (C) 2005 Jean-Sebastien Senecal (js@drone.ws)
 * This file is a Frei0r plugin.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "frei0r.hpp"
#include "frei0r_math.h"
#include <string.h>

#include <cstring>

class equaliz0r : public frei0r::filter
{
  // Look-up tables for equaliz0r values.
  unsigned char rlut[256];
  unsigned char glut[256];
  unsigned char blut[256];
  
  // Intensity histograms.
  unsigned int rhist[256];
  unsigned int ghist[256];
  unsigned int bhist[256];

  void updateLookUpTables()
  {
    unsigned int size = width*height;
    
    // First pass : build histograms.
    
    // Reset histograms.
    memset(rhist, 0, 256*sizeof(unsigned int));
    memset(ghist, 0, 256*sizeof(unsigned int));
    memset(bhist, 0, 256*sizeof(unsigned int));

    // Update histograms.
    const unsigned char *in_ptr = (const unsigned char*) in;
    for (unsigned int i=0; i<size; ++i)
    {
      // update 'em
      rhist[*in_ptr++]++;
      ghist[*in_ptr++]++;
      bhist[*in_ptr++]++;
      in_ptr++; // skip alpha
    }

    // Second pass : update look-up tables.
    in_ptr = (const unsigned char*) in;

    // Cumulative intensities of histograms.
    unsigned int
      rcum = 0,
      gcum = 0,
      bcum = 0;
      
    for (int i=0; i<256; ++i)
    {
      // update cumulatives
      rcum += rhist[i];
      gcum += ghist[i];
      bcum += bhist[i];
      
      // update 'em
      rlut[i] = CLAMP0255( (rcum << 8) / size ); // = 256 * rcum / size
      glut[i] = CLAMP0255( (gcum << 8) / size ); // = 256 * gcum / size
      blut[i] = CLAMP0255( (bcum << 8) / size ); // = 256 * bcum / size
      
      in_ptr++; // skip alpha
    }

  }
  
public:
  equaliz0r(unsigned int width, unsigned int height)
  {
  }
  
  virtual void update()
  {
    std::copy(in, in + width*height, out);
    updateLookUpTables();
    unsigned int size = width*height;
    const unsigned char *in_ptr = (const unsigned char*) in;
    unsigned char *out_ptr = (unsigned char*) out;
    for (unsigned int i=0; i<size; ++i)
    {
      *out_ptr++ = rlut[*in_ptr++];
      *out_ptr++ = glut[*in_ptr++];
      *out_ptr++ = blut[*in_ptr++];
      *out_ptr++ = *in_ptr++; // copy alpha
    }
  }
};


frei0r::construct<equaliz0r> plugin("Equaliz0r",
                                    "Equalizes the intensity histograms",
                                    "Jean-Sebastien Senecal (Drone)",
                                    0,1,
                                    F0R_COLOR_MODEL_RGBA8888);