1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.filtershow.filters;
18
19import java.util.Arrays;
20
21public class ColorSpaceMatrix {
22    private final float[] mMatrix = new float[16];
23    private static final float RLUM = 0.3086f;
24    private static final float GLUM = 0.6094f;
25    private static final float BLUM = 0.0820f;
26
27    public ColorSpaceMatrix() {
28        identity();
29    }
30
31    /**
32     * Copy constructor
33     *
34     * @param matrix
35     */
36    public ColorSpaceMatrix(ColorSpaceMatrix matrix) {
37        System.arraycopy(matrix.mMatrix, 0, mMatrix, 0, matrix.mMatrix.length);
38    }
39
40    /**
41     * get the matrix
42     *
43     * @return the internal matrix
44     */
45    public float[] getMatrix() {
46        return mMatrix;
47    }
48
49    /**
50     * set matrix to identity
51     */
52    public void identity() {
53        Arrays.fill(mMatrix, 0);
54        mMatrix[0] = mMatrix[5] = mMatrix[10] = mMatrix[15] = 1;
55    }
56
57    public void convertToLuminance() {
58        mMatrix[0] = mMatrix[1] = mMatrix[2] = 0.3086f;
59        mMatrix[4] = mMatrix[5] = mMatrix[6] = 0.6094f;
60        mMatrix[8] = mMatrix[9] = mMatrix[10] = 0.0820f;
61    }
62
63    private void multiply(float[] a)
64    {
65        int x, y;
66        float[] temp = new float[16];
67
68        for (y = 0; y < 4; y++) {
69            int y4 = y * 4;
70            for (x = 0; x < 4; x++) {
71                temp[y4 + x] = mMatrix[y4 + 0] * a[x]
72                        + mMatrix[y4 + 1] * a[4 + x]
73                        + mMatrix[y4 + 2] * a[8 + x]
74                        + mMatrix[y4 + 3] * a[12 + x];
75            }
76        }
77        for (int i = 0; i < 16; i++)
78            mMatrix[i] = temp[i];
79    }
80
81    private void xRotateMatrix(float rs, float rc)
82    {
83        ColorSpaceMatrix c = new ColorSpaceMatrix();
84        float[] tmp = c.mMatrix;
85
86        tmp[5] = rc;
87        tmp[6] = rs;
88        tmp[9] = -rs;
89        tmp[10] = rc;
90
91        multiply(tmp);
92    }
93
94    private void yRotateMatrix(float rs, float rc)
95    {
96        ColorSpaceMatrix c = new ColorSpaceMatrix();
97        float[] tmp = c.mMatrix;
98
99        tmp[0] = rc;
100        tmp[2] = -rs;
101        tmp[8] = rs;
102        tmp[10] = rc;
103
104        multiply(tmp);
105    }
106
107    private void zRotateMatrix(float rs, float rc)
108    {
109        ColorSpaceMatrix c = new ColorSpaceMatrix();
110        float[] tmp = c.mMatrix;
111
112        tmp[0] = rc;
113        tmp[1] = rs;
114        tmp[4] = -rs;
115        tmp[5] = rc;
116        multiply(tmp);
117    }
118
119    private void zShearMatrix(float dx, float dy)
120    {
121        ColorSpaceMatrix c = new ColorSpaceMatrix();
122        float[] tmp = c.mMatrix;
123
124        tmp[2] = dx;
125        tmp[6] = dy;
126        multiply(tmp);
127    }
128
129    /**
130     * sets the transform to a shift in Hue
131     *
132     * @param rot rotation in degrees
133     */
134    public void setHue(float rot)
135    {
136        float mag = (float) Math.sqrt(2.0);
137        float xrs = 1 / mag;
138        float xrc = 1 / mag;
139        xRotateMatrix(xrs, xrc);
140        mag = (float) Math.sqrt(3.0);
141        float yrs = -1 / mag;
142        float yrc = (float) Math.sqrt(2.0) / mag;
143        yRotateMatrix(yrs, yrc);
144
145        float lx = getRedf(RLUM, GLUM, BLUM);
146        float ly = getGreenf(RLUM, GLUM, BLUM);
147        float lz = getBluef(RLUM, GLUM, BLUM);
148        float zsx = lx / lz;
149        float zsy = ly / lz;
150        zShearMatrix(zsx, zsy);
151
152        float zrs = (float) Math.sin(rot * Math.PI / 180.0);
153        float zrc = (float) Math.cos(rot * Math.PI / 180.0);
154        zRotateMatrix(zrs, zrc);
155        zShearMatrix(-zsx, -zsy);
156        yRotateMatrix(-yrs, yrc);
157        xRotateMatrix(-xrs, xrc);
158    }
159
160    /**
161     * set it to a saturation matrix
162     *
163     * @param s
164     */
165    public void changeSaturation(float s) {
166        mMatrix[0] = (1 - s) * RLUM + s;
167        mMatrix[1] = (1 - s) * RLUM;
168        mMatrix[2] = (1 - s) * RLUM;
169        mMatrix[4] = (1 - s) * GLUM;
170        mMatrix[5] = (1 - s) * GLUM + s;
171        mMatrix[6] = (1 - s) * GLUM;
172        mMatrix[8] = (1 - s) * BLUM;
173        mMatrix[9] = (1 - s) * BLUM;
174        mMatrix[10] = (1 - s) * BLUM + s;
175    }
176
177    /**
178     * Transform RGB value
179     *
180     * @param r red pixel value
181     * @param g green pixel value
182     * @param b blue pixel value
183     * @return computed red pixel value
184     */
185    public float getRed(int r, int g, int b) {
186        return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
187    }
188
189    /**
190     * Transform RGB value
191     *
192     * @param r red pixel value
193     * @param g green pixel value
194     * @param b blue pixel value
195     * @return computed green pixel value
196     */
197    public float getGreen(int r, int g, int b) {
198        return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
199    }
200
201    /**
202     * Transform RGB value
203     *
204     * @param r red pixel value
205     * @param g green pixel value
206     * @param b blue pixel value
207     * @return computed blue pixel value
208     */
209    public float getBlue(int r, int g, int b) {
210        return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
211    }
212
213    private float getRedf(float r, float g, float b) {
214        return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
215    }
216
217    private float getGreenf(float r, float g, float b) {
218        return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
219    }
220
221    private float getBluef(float r, float g, float b) {
222        return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
223    }
224
225}
226