1 /*
2 * feColorMatrix filter primitive renderer
3 *
4 * Authors:
5 * Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
6 *
7 * Copyright (C) 2007 authors
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
12 #include "display/nr-filter-colormatrix.h"
13 #include "display/nr-filter-utils.h"
14 #include<math.h>
16 namespace NR {
18 FilterColorMatrix::FilterColorMatrix()
19 {
20 }
22 FilterPrimitive * FilterColorMatrix::create() {
23 return new FilterColorMatrix();
24 }
26 FilterColorMatrix::~FilterColorMatrix()
27 {}
29 int FilterColorMatrix::render(FilterSlot &slot, Matrix const &trans) {
30 NRPixBlock *in = slot.get(_input);
31 NRPixBlock *out = new NRPixBlock;
33 nr_pixblock_setup_fast(out, in->mode,
34 in->area.x0, in->area.y0, in->area.x1, in->area.y1,
35 true);
37 unsigned char *in_data = NR_PIXBLOCK_PX(in);
38 unsigned char *out_data = NR_PIXBLOCK_PX(out);
39 unsigned char r,g,b,a;
40 int x,y,x0,y0,x1,y1,i;
41 double a00,a01,a02,a10,a11,a12,a20,a21,a22, coshue, sinhue;
42 x0=in->area.x0;
43 y0=in->area.y0;
44 x1=in->area.x1;
45 y1=in->area.y1;
47 switch(type){
48 case COLORMATRIX_MATRIX:
49 if (values.size()!=20) {
50 g_warning("ColorMatrix: values parameter error. Wrong size.");
51 return -1;
52 }
53 for (x=x0;x<x1;x++){
54 for (y=y0;y<y1;y++){
55 i = ((x-x0) + (x1-x0)*(y-y0))*4;
56 r = in_data[i];
57 g = in_data[i+1];
58 b = in_data[i+2];
59 a = in_data[i+3];
60 out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + values[4] );
61 out_data[i+1] = CLAMP_D_TO_U8( r*values[5] + g*values[6] + b*values[7] + a*values[8] + values[9] );
62 out_data[i+2] = CLAMP_D_TO_U8( r*values[10] + g*values[11] + b*values[12] + a*values[13] + values[14] );
63 out_data[i+3] = CLAMP_D_TO_U8( r*values[15] + g*values[16] + b*values[17] + a*values[18] + values[19] );
64 }
65 }
66 break;
67 case COLORMATRIX_SATURATE:
68 for (x=x0;x<x1;x++){
69 for (y=y0;y<y1;y++){
70 i = ((x-x0) + (x1-x0)*(y-y0))*4;
71 r = in_data[i];
72 g = in_data[i+1];
73 b = in_data[i+2];
74 a = in_data[i+3];
75 out_data[i] = CLAMP_D_TO_U8( r*(0.213+0.787*value) + g*(0.715-0.715*value) + b*(0.072-0.072*value) );
76 out_data[i+1] = CLAMP_D_TO_U8( r*(0.213-0.213*value) + g*(0.715+0.285*value) + b*(0.072-0.072*value) );
77 out_data[i+2] = CLAMP_D_TO_U8( r*(0.213-0.213*value) + g*(0.715-0.715*value) + b*(0.072+0.928*value) );
78 out_data[i+3] = a;
79 }
80 }
81 break;
82 case COLORMATRIX_HUEROTATE:
83 coshue = cos(value);
84 sinhue = sin(value);
85 a00 = 0.213 + coshue*( 0.787) + sinhue*(-0.213);
86 a01 = 0.715 + coshue*(-0.715) + sinhue*(-0.715);
87 a02 = 0.072 + coshue*(-0.072) + sinhue*( 0.928);
88 a10 = 0.213 + coshue*(-0.213) + sinhue*( 0.143);
89 a11 = 0.715 + coshue*( 0.285) + sinhue*( 0.140);
90 a12 = 0.072 + coshue*(-0.072) + sinhue*(-0.283);
91 a20 = 0.213 + coshue*(-0.213) + sinhue*(-0.787);
92 a21 = 0.715 + coshue*(-0.715) + sinhue*( 0.715);
93 a22 = 0.072 + coshue*( 0.928) + sinhue*( 0.072);
95 for (x=x0;x<x1;x++){
96 for (y=y0;y<y1;y++){
97 i = ((x-x0) + (x1-x0)*(y-y0))*4;
98 r = in_data[i];
99 g = in_data[i+1];
100 b = in_data[i+2];
101 a = in_data[i+3];
103 out_data[i] = CLAMP_D_TO_U8( r*a00 + g*a01 + b*a02 );
104 out_data[i+1] = CLAMP_D_TO_U8( r*a10 + g*a11 + b*a12 );
105 out_data[i+2] = CLAMP_D_TO_U8( r*a20 + g*a21 + b*a22 );
106 out_data[i+3] = a;
107 }
108 }
109 break;
110 case COLORMATRIX_LUMINANCETOALPHA:
111 for (x=x0;x<x1;x++){
112 for (y=y0;y<y1;y++){
113 i = ((x-x0) + (x1-x0)*(y-y0))*4;
114 r = in_data[i];
115 g = in_data[i+1];
116 b = in_data[i+2];
117 out_data[i] = 0;
118 out_data[i+1] = 0;
119 out_data[i+2] = 0;
120 out_data[i+3] = CLAMP_D_TO_U8( r*0.2125 + g*0.7154 + b*0.0721);
121 }
122 }
123 break;
124 case COLORMATRIX_ENDTYPE:
125 break;
126 }
127 out->empty = FALSE;
128 slot.set(_output, out);
129 return 0;
130 }
132 void FilterColorMatrix::area_enlarge(NRRectL &area, Matrix const &trans)
133 {
134 }
136 void FilterColorMatrix::set_type(FilterColorMatrixType t){
137 type = t;
138 }
140 void FilterColorMatrix::set_value(gdouble v){
141 value = v;
142 }
144 void FilterColorMatrix::set_values(std::vector<gdouble> &v){
145 values = v;
146 }
148 } /* namespace NR */
150 /*
151 Local Variables:
152 mode:c++
153 c-file-style:"stroustrup"
154 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
155 indent-tabs-mode:nil
156 fill-column:99
157 End:
158 */
159 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :