blob: 0d82f6ac28bb7fc4f41b0077df3aeda71436944e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui.style;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
/**
* A utility class to do various color manipulations
*/
public class YUV_RGBConverter {
/**
* This class "holds" the YUV values corresponding to RGB color
*/
public class YUV {
class NormalizedRGB {
double blue;
double green;
private final double maxRGB = 256.0;
double red;
public NormalizedRGB(RGB rgb) {
// first normalize to between 0 - 1
red = rgb.red / maxRGB;
green = rgb.green / maxRGB;
blue = rgb.blue / maxRGB;
red = gammaNormalized(red);
green = gammaNormalized(green);
blue = gammaNormalized(blue);
}
}
private NormalizedRGB normalizedRGB;
RGB originalRGB;
private double u = -1;
private double v = -1;
private double y = -1;
private YUV() {
super();
}
public YUV(double y, double u, double v) {
this();
this.y = y;
this.u = u;
this.v = v;
}
public YUV(RGB rgb) {
this();
originalRGB = rgb;
normalizedRGB = new NormalizedRGB(rgb);
// force calculations
getY();
getV();
getU();
}
/**
* normalize to "average" gamma 2.2222 or 1/0.45
*/
double gammaNormalized(double colorComponent) {
if (colorComponent < 0.018) {
return colorComponent * 0.45;
} else {
return 1.099 * Math.pow(colorComponent, 0.45) - 0.099;
}
}
/**
* @return RGB based on original RGB and current YUV values;
*/
public RGB getRGB() {
RGB result = null;
double r = getY() + 1.14 * getV();
double g = getY() - 0.395 * getU() - 0.58 * getV();
double b = getY() + 2.032 * getU();
int red = (int) (inverseGammaNormalized(r) * 256);
int green = (int) (inverseGammaNormalized(g) * 256);
int blue = (int) (inverseGammaNormalized(b) * 256);
if (red < 0)
red = 0;
else if (red > 255)
red = 255;
if (green < 0)
green = 0;
else if (green > 255)
green = 255;
if (blue < 0)
blue = 0;
else if (blue > 255)
blue = 255;
result = new RGB(red, green, blue);
return result;
}
public double getU() {
if (u == -1) {
u = 0.4949 * (normalizedRGB.blue - getY());
}
return u;
}
public double getV() {
if (v == -1) {
v = 0.877 * (normalizedRGB.red - getY());
}
return v;
}
public double getY() {
if (y == -1) {
y = 0.299 * normalizedRGB.red + 0.587 * normalizedRGB.green + 0.114 * normalizedRGB.blue;
}
return y;
}
double inverseGammaNormalized(double colorComponent) {
if (colorComponent < 0.018) {
return colorComponent * .222;
} else {
return Math.pow(((.9099 * colorComponent + 0.09)), 2.22);
}
}
}
public YUV_RGBConverter() {
super();
}
public double calculateYComponent(Color targetColor) {
return new YUV(targetColor.getRGB()).getY();
}
public RGB transformRGB(RGB originalRGB, double scaleFactor, double target) {
RGB transformedRGB = null;
//CCIR601 yuv = new CCIR601(originalRGB);
YUV yuv = new YUV(originalRGB);
double y = yuv.getY();
// zero is black, one is white
if (y < target) {
// is "dark" make lighter
y = y + ((target - y) * scaleFactor);
} else {
// is "light" make darker
y = y - ((y - target) * scaleFactor);
}
//yuv.setY(y);
YUV newYUV = new YUV(y, yuv.getU(), yuv.getV());
//CCIR601 newYUV = new CCIR601(y, yuv.getCb601(), yuv.getCr601());
transformedRGB = newYUV.getRGB();
return transformedRGB;
}
public RGB transformRGBToGrey(RGB originalRGB, double scaleFactor, double target) {
RGB transformedRGB = null;
// we left the "full" API method signature, but this
// version does not take into account originalRGB, though
// it might someday.
// for now, we'll simply make the new RGB grey, either a little
// lighter, or a little darker than background.
double y = 0;
double mid = 0.5;
// zero is black, one is white
if (target < mid) {
// is "dark" make lighter
y = target + scaleFactor;
} else {
// is "light" make darker
y = target - scaleFactor;
}
int c = (int) Math.round(y * 255);
// just to gaurd against mis-use, or scale's values greater
// than mid point (and possibly rounding error)
if (c > 255)
c = 255;
if (c < 0)
c = 0;
transformedRGB = new RGB(c, c, c);
return transformedRGB;
}
}