/*
* Image/J Plugins
* Copyright (C) 2002-2009 Jarek Sacha
* Author's email: jsacha at users dot sourceforge dot net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Latest release available at http://sourceforge.net/projects/ij-plugins/
*/
package net.sf.ij_plugins.color;
import ij.IJ;
import ij.process.ByteProcessor;
import ij.process.ColorProcessor;
import net.sf.ij_plugins.multiband.VectorProcessor;
import net.sf.ij_plugins.util.Validate;
import net.sf.ij_plugins.util.progress.ProgressEvent;
import net.sf.ij_plugins.util.progress.ProgressListener;
/**
* Basic color space conversion utilities, assuming two degree observer and illuminant D65.
*
* @author Jarek Sacha
* @version $Revision: 1.7 $
*/
public final class ColorSpaceConvertion {
private static final double X_D65 = 0.950467;
private static final double Y_D65 = 1.0000;
private static final double Z_D65 = 1.088969;
private static final double CIE_EPSILON = 0.008856;
private static final double CIE_KAPPA = 903.3;
private static final double CIE_KAPPA_EPSILON = CIE_EPSILON * CIE_KAPPA;
private ColorSpaceConvertion() {
}
/**
* Conversion from CIE XYZ to sRGB as defined in the IEC 619602-1 standard
* (http://www.colour.org/tc8-05/Docs/colorspace/61966-2-1.pdf)
* <pre>
* r_linear = +3.2406 * X - 1.5372 * Y - 0.4986 * Z;
* g_linear = -0.9689 * X + 1.8758 * Y + 0.0415 * Z;
* b_linear = +0.0557 * X - 0.2040 * Y + 1.0570 * Z;
* r = r_linear > 0.0031308
* ? 1.055 * Math.pow(r_linear, (1 / 2.4)) - 0.055
* : 12.92 * r_linear;
* g = g_linear > 0.0031308
* ? 1.055 * Math.pow(g_linear, (1 / 2.4)) - 0.055
* : 12.92 * g_linear;
* b = b_linear > 0.0031308
* ? 1.055 * Math.pow(b_linear, (1 / 2.4)) - 0.055
* : 12.92 * b_linear;
* R = r * 255
* G = r * 255
* B = r * 255
* <pre>
*
* @param xyz input CIE XYZ values.
* @param rgb output sRGB values in [0, 255] range.
*/
public static void xyzToRGB(final float[] xyz, final float[] rgb) {
final double x = xyz[0];
final double y = xyz[1];
final double z = xyz[2];
// http://www.colour.org/tc8-05/Docs/colorspace/61966-2-1.pdf
final double r_linear = +3.2406 * x - 1.5372 * y - 0.4986 * z;
final double g_linear = -0.9689 * x + 1.8758 * y + 0.0415 * z;
final double b_linear = +0.0557 * x - 0.2040 * y + 1.0570 * z;
final double r = r_linear > 0.0031308
? 1.055 * Math.pow(r_linear, (1 / 2.4)) - 0.055
: 12.92 * r_linear;
final double g = g_linear > 0.0031308
? 1.055 * Math.pow(g_linear, (1 / 2.4)) - 0.055
: 12.92 * g_linear;
final double b = b_linear > 0.0031308
? 1.055 * Math.pow(b_linear, (1 / 2.4)) - 0.055
: 12.92 * b_linear;
rgb[0] = (float) (r * 255);
rgb[1] = (float) (g * 255);
rgb[2] = (float) (b * 255);
}
/**
* Conversion from CIE L*a*b* to CIE XYZ assuming Observer. = 2, Illuminant = D65.
* Conversion based on formulas provided at http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
*
* @param lab input CIE L*a*b* values.
* @param xyz output CIE XYZ values.
*/
public static void labToXYZ(final float[] lab, final float[] xyz) {
final double l = lab[0];
final double a = lab[1];
final double b = lab[2];
final double yr = l > CIE_KAPPA_EPSILON
? Math.pow((l + 16) / 116, 3)
: l / CIE_KAPPA;
final double fy = yr > CIE_EPSILON
? (l + 16) / 116.0
: (CIE_KAPPA * yr + 16) / 116.0;
final double fx = a / 500 + fy;
final double fx3 = fx * fx * fx;
final double xr = fx3 > CIE_EPSILON
? fx3
: (116 * fx - 16) / CIE_KAPPA;
final double fz = fy - b / 200.0;
final double fz3 = fz * fz * fz;
final double zr = fz3 > CIE_EPSILON
? fz3
: (116 * fz - 16) / CIE_KAPPA;
xyz[0] = (float) (xr * X_D65);
xyz[1] = (float) (yr * Y_D65);
xyz[2] = (float) (zr * Z_D65);
}
/**
* Conversion from sRGB to CIE XYZ as defined in the IEC 619602-1 standard
* (http://www.colour.org/tc8-05/Docs/colorspace/61966-2-1.pdf)
* <pre>
* r = R / 255;
* g = G / 255;
* b = B / 255;
* r_linear = r > 0.04045
* ? Math.pow((r + 0.055) / 1.055, 2.4)
* : r / 12.92;
* g_linear = g > 0.04045
* ? Math.pow((g + 0.055) / 1.055, 2.4)
* : g / 12.92;
* b_linear = b > 0.04045
* ? Math.pow((b + 0.055) / 1.055, 2.4)
* : b / 12.92;
* X = 0.4124 * r_linear + 0.3576 * g_linear + 0.1805 * b_linear;
* Y = 0.2126 * r_linear + 0.7152 * g_linear + 0.0722 * b_linear;
* Z = 0.0193 * r_linear + 0.1192 * g_linear + 0.9505 * b_linear;
* </pre>
*
* @param rgb source sRGB values. Size of array <code>rgb</code> must be at least 3. If size of
* array <code>rgb</code> larger than three then only first 3 values are used.
* @param xyz destinaltion CIE XYZ values. Size of array <code>xyz</code> must be at least 3. If
* size of array <code>xyz</code> larger than three then only first 3 values are
* used.
*/
public static void rgbToXYZ(final float[] rgb, final float[] xyz) {
final double r = rgb[0] / 255;
final double g = rgb[1] / 255;
final double b = rgb[2] / 255;
final double r_linear = r > 0.04045
? Math.pow((r + 0.055) / 1.055, 2.4)
: r / 12.92;
final double g_linear = g > 0.04045
? Math.pow((g + 0.055) / 1.055, 2.4)
: g / 12.92;
final double b_linear = b > 0.04045
? Math.pow((b + 0.055) / 1.055, 2.4)
: b / 12.92;
final double x = 0.4124 * r_linear + 0.3576 * g_linear + 0.1805 * b_linear;
final double y = 0.2126 * r_linear + 0.7152 * g_linear + 0.0722 * b_linear;
final double z = 0.0193 * r_linear + 0.1192 * g_linear + 0.9505 * b_linear;
xyz[0] = (float) x;
xyz[1] = (float) y;
xyz[2] = (float) z;
}
/**
* /**
* Conversion from CIE XYZ to CIE L*a*b* assuming Observer. = 2, Illuminant = D65.
* Conversion based on formulas provided at http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
*
* @param xyz source CIE XYZ values. Size of array <code>xyz</code> must be at least 3. If size of
* array <code>xyz</code> larger than three then only first 3 values are used.
* @param lab destinaltion CIE L*a*b* values. Size of array <code>lab</code> must be at least 3.
* If size of array <code>lab</code> larger than three then only first 3 values are
* used.
*/
public static void xyzToLab(final float[] xyz, final float[] lab) {
final double xr = xyz[0] / X_D65;
final double yr = xyz[1] / Y_D65;
final double zr = xyz[2] / Z_D65;
final double fx = xr > CIE_EPSILON
? Math.pow(xr, 1.0 / 3.0)
: (CIE_KAPPA * xr + 16) / 116.0;
final double fy = yr > CIE_EPSILON
? Math.pow(yr, 1.0 / 3.0)
: (CIE_KAPPA * yr + 16) / 116.0;
final double fz = zr > CIE_EPSILON
? Math.pow(zr, 1.0 / 3.0)
: (CIE_KAPPA * zr + 16) / 116.0;
lab[0] = (float) (116 * fy - 16);
lab[1] = (float) (500 * (fx - fy));
lab[2] = (float) (200 * (fy - fz));
}
/**
* Convert between RGB and CIE L*a*b* color image representation.
*
* @param cp RGB image to be converted
* @return CIE L*a*b* image represented by {@link VectorProcessor}.
*/
public static VectorProcessor rgbToLabVectorProcessor
(
final ColorProcessor cp) {
final VectorProcessor vp = new VectorProcessor(cp);
final float[][] pixels = vp.getPixels();
final float[] tmp = new float[3];
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(pixels.length / 10, 1);
for (int i = 0; i < pixels.length; i++) {
if (i % progressStep == 0) {
IJ.showProgress(i, pixels.length);
}
final float[] pixel = pixels[i];
ColorSpaceConvertion.rgbToXYZ(pixel, tmp);
ColorSpaceConvertion.xyzToLab(tmp, pixel);
}
IJ.showProgress(pixels.length, pixels.length);
return vp;
}
/**
* Convert between sRGB and XYZ color image representation.
*
* @param cp RGB image to be converted
* @return XYZ image represented by {@link VectorProcessor}.
*/
public static VectorProcessor rgbToXYZVectorProcessor(final ColorProcessor cp) {
final VectorProcessor vp = new VectorProcessor(cp);
final float[][] pixels = vp.getPixels();
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(pixels.length / 10, 1);
for (int i = 0; i < pixels.length; i++) {
if (i % progressStep == 0) {
IJ.showProgress(i, pixels.length);
}
final float[] pixel = pixels[i];
// Replace sRGB content with XYZ
ColorSpaceConvertion.rgbToXYZ(pixel, pixel);
}
IJ.showProgress(pixels.length, pixels.length);
return vp;
}
/**
* Convert between CIE L*a*b* and RGB color image representation.
*
* @param vp CIE L*a*b* image represented by {@link VectorProcessor}.
* @return RGB image represented by a {@link ColorProcessor}.
*/
public static ColorProcessor labToColorProcessor(final VectorProcessor vp) {
final float[][] pixels = vp.getPixels();
final float[] tmpXYZ = new float[3];
final float[] tmpRGB = new float[3];
final int width = vp.getWidth();
final int height = vp.getHeight();
final int sliceSize = width * height;
final byte[] red = new byte[sliceSize];
final byte[] green = new byte[sliceSize];
final byte[] blue = new byte[sliceSize];
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(pixels.length / 10, 1);
for (int i = 0; i < pixels.length; i++) {
if (i % progressStep == 0) {
IJ.showProgress(i, pixels.length);
}
final float[] pixel = pixels[i];
ColorSpaceConvertion.labToXYZ(pixel, tmpXYZ);
ColorSpaceConvertion.xyzToRGB(tmpXYZ, tmpRGB);
int r = Math.min(Math.max(Math.round(tmpRGB[0]), 0), 255);
int g = Math.min(Math.max(Math.round(tmpRGB[1]), 0), 255);
int b = Math.min(Math.max(Math.round(tmpRGB[2]), 0), 255);
red[i] = (byte) (r & 0xff);
green[i] = (byte) (g & 0xff);
blue[i] = (byte) (b & 0xff);
}
IJ.showProgress(pixels.length, pixels.length);
final ColorProcessor cp = new ColorProcessor(width, height);
cp.setRGB(red, green, blue);
return cp;
}
/**
* Convert between XYZ and RGB color image representation.
*
* @param vp XYZ image represented by {@link VectorProcessor}.
* @return RGB image represented by a {@link ColorProcessor}.
*/
public static ColorProcessor xyzToColorProcessor(final VectorProcessor vp) {
final float[][] pixels = vp.getPixels();
final float[] rgb = new float[3];
final int width = vp.getWidth();
final int height = vp.getHeight();
final int sliceSize = width * height;
final byte[] red = new byte[sliceSize];
final byte[] green = new byte[sliceSize];
final byte[] blue = new byte[sliceSize];
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(pixels.length / 10, 1);
for (int i = 0; i < pixels.length; i++) {
if (i % progressStep == 0) {
IJ.showProgress(i, pixels.length);
}
final float[] pixel = pixels[i];
ColorSpaceConvertion.xyzToRGB(pixel, rgb);
int r = Math.min(Math.max(Math.round(rgb[0]), 0), 255);
int g = Math.min(Math.max(Math.round(rgb[1]), 0), 255);
int b = Math.min(Math.max(Math.round(rgb[2]), 0), 255);
red[i] = (byte) (r & 0xff);
green[i] = (byte) (g & 0xff);
blue[i] = (byte) (b & 0xff);
}
IJ.showProgress(pixels.length, pixels.length);
final ColorProcessor cp = new ColorProcessor(width, height);
cp.setRGB(red, green, blue);
return cp;
}
/**
* Converts image pixels from RGB color space to YCbCr color space. Uses formulas provided at:
* <a href="http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30">
* http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30</a>. See also:
* <a href="http://en.wikipedia.org/wiki/YCbCr">http://en.wikipedia.org/wiki/YCbCr</a>.
* <p/>
* YCbCb (601) from "digital 8-bit RGB "
* <pre>
* ========================================================================
* Y = 16 + 1/256 * ( 65.738 * R + 129.057 * G + 25.064 * B)
* Cb = 128 + 1/256 * ( - 37.945 * R - 74.494 * G + 112.439 * B)
* Cr = 128 + 1/256 * ( 112.439 * R - 94.154 * G - 18.285 * B)
* ........................................................................
* R, G, B in {0, 1, 2, ..., 255}
* Y in {16, 17, ..., 235}
* with footroom in {1, 2, ..., 15}
* headroom in {236, 237, ..., 254}
* sync. in {0, 255}
* Cb, Cr in {16, 17, ..., 240}
* </pre>
*
* @param rgb source RGB (cannot be null).
* @param ybr destination Y, Cb, and Cr (cannot be null).
*/
static void rgbToYCbCr(byte[] rgb, byte[] ybr) {
final int r = 0xff & rgb[0];
final int g = 0xff & rgb[1];
final int b = 0xff & rgb[2];
final double y = 16 + 0.25678906250000 * r + 0.50412890625000 * g + 0.09790625000000 * b;
final double cb = 128 - 0.14822265625000 * r - 0.29099218750000 * g + 0.43921484375000 * b;
final double cr = 128 + 0.43921484375000 * r - 0.36778906250000 * g - 0.07142578125000 * b;
ybr[0] = (byte) (0xff & Math.min(Math.max(Math.round(y), 0), 255));
ybr[1] = (byte) (0xff & Math.min(Math.max(Math.round(cb), 0), 255));
ybr[2] = (byte) (0xff & Math.min(Math.max(Math.round(cr), 0), 255));
}
/**
* Converts image pixels from RGB color space to YCbCr color space. Uses formulas provided at:
* <a href="http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30">
* http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30</a>. See also:
* <a href="http://en.wikipedia.org/wiki/YCbCr">http://en.wikipedia.org/wiki/YCbCr</a>.
* <p/>
* YCbCb (601) from "digital 8-bit RGB "
* <pre>
* ========================================================================
* Y = 16 + 1/256 * ( 65.738 * R + 129.057 * G + 25.064 * B)
* Cb = 128 + 1/256 * ( - 37.945 * R - 74.494 * G + 112.439 * B)
* Cr = 128 + 1/256 * ( 112.439 * R - 94.154 * G - 18.285 * B)
* ........................................................................
* R, G, B in {0, 1, 2, ..., 255}
* Y in {16, 17, ..., 235}
* with footroom in {1, 2, ..., 15}
* headroom in {236, 237, ..., 254}
* sync. in {0, 255}
* Cb, Cr in {16, 17, ..., 240}
* </pre>
*
* @param src source image.
* @param progressListener progress listener.
* @return array of color bands: Y, Cb, Cr, respectively.
*/
public static ByteProcessor[] rgbToYCbCr(final ColorProcessor src, final ProgressListener progressListener) {
final String progressMessage = "Converting RGB to YCbCr...";
if (progressListener != null) {
progressListener.progressNotification(new ProgressEvent(src, 0.0, progressMessage));
}
final int width = src.getWidth();
final int height = src.getHeight();
final int nbPixels = width * height;
final byte[] rPixels = new byte[nbPixels];
final byte[] gPixels = new byte[nbPixels];
final byte[] bPixels = new byte[nbPixels];
src.getRGB(rPixels, gPixels, bPixels);
final byte[] yPixels = new byte[nbPixels];
final byte[] cbPixels = new byte[nbPixels];
final byte[] crPixels = new byte[nbPixels];
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(1, nbPixels / 10);
final byte[] rgb = new byte[3];
final byte[] ybr = new byte[3];
for (int i = 0; i < nbPixels; i++) {
rgb[0] = rPixels[i];
rgb[1] = gPixels[i];
rgb[2] = bPixels[i];
rgbToYCbCr(rgb, ybr);
yPixels[i] = ybr[0];
cbPixels[i] = ybr[1];
crPixels[i] = ybr[2];
if ((progressListener != null) && (i % progressStep == 0)) {
progressListener.progressNotification(new ProgressEvent(src, i / (double) nbPixels, progressMessage));
}
}
if (progressListener != null) {
progressListener.progressNotification(new ProgressEvent(src, 1.0, progressMessage));
}
return new ByteProcessor[]{
new ByteProcessor(width, height, yPixels, null),
new ByteProcessor(width, height, cbPixels, null),
new ByteProcessor(width, height, crPixels, null),
};
}
/**
* Converts image pixels from RGB color space to YCbCr color space.
* Equivalent to calling <code>rgbToYCbCr(rgb, null)</code>.
*
* @param rgb inpuit image in sRGB color space.
* @return array of ByteProcessor representing color planes: Y, Cb, and Cr.
* @see #rgbToYCbCr(ij.process.ColorProcessor,net.sf.ij_plugins.util.progress.ProgressListener)
*/
public static ByteProcessor[] rgbToYCbCr(final ColorProcessor rgb) {
return rgbToYCbCr(rgb, null);
}
/**
* Converts image pixels from RGB color space to YCbCr color space. Uses formulas provided at:
* <a href="http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30">
* http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30</a>. See also:
* <a href="http://en.wikipedia.org/wiki/YCbCr">http://en.wikipedia.org/wiki/YCbCr</a>.
* <p/>
* "digital 8-bit RGB" from YCbCb (601)
* <pre>
* ========================================================================
* R = 1/256 * (298.081952524118 * (Y -16) + 0.001711624973 * (Cb - 128) + 408.582641764512 * (Cr-128))
* G = 1/256 * (298.081952524118 * (Y -16) - 100.290891128080 * (Cb - 128) - 208.120396471735 * (Cr-128))
* B = 1/256 * (298.081952524118 * (Y -16) + 516.412147108167 * (Cb - 128) - 0.000466679809 * (Cr-128))
* </pre>
*
* @param ybr source Y, Cb, and Cr (cannot ne null).
* @param rgb destination RGB (cannot be null).
*/
public static void ycbcrToRGB(final byte[] ybr, final byte[] rgb) {
final int y = (0xff & ybr[0]) - 16;
final int cb = (0xff & ybr[1]) - 128;
final int cr = (0xff & ybr[2]) - 128;
final double r = 1.16438262704734 * y - 0.00000668603505 * cb + 1.59602594439262 * cr;
final double g = 1.16438262704734 * y - 0.39176129346906 * cb - 0.81297029871772 * cr;
final double b = 1.16438262704734 * y + 2.01723494964128 * cb - 0.00000182296800 * cr;
rgb[0] = (byte) (0xff & Math.min(Math.max(Math.round(r), 0), 255));
rgb[1] = (byte) (0xff & Math.min(Math.max(Math.round(g), 0), 255));
rgb[2] = (byte) (0xff & Math.min(Math.max(Math.round(b), 0), 255));
}
/**
* Converts image pixels from RGB color space to YCbCr color space. Uses formulas provided at:
* <a href="http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30">
* http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30</a>. See also:
* <a href="http://en.wikipedia.org/wiki/YCbCr">http://en.wikipedia.org/wiki/YCbCr</a>.
* <p/>
* "digital 8-bit RGB" from YCbCb (601)
* <pre>
* ========================================================================
* R = 1/256 * (298.081952524118 * (Y -16) + 0.001711624973 * (Cb - 128) + 408.582641764512 * (Cr-128))
* G = 1/256 * (298.081952524118 * (Y -16) - 100.290891128080 * (Cb - 128) - 208.120396471735 * (Cr-128))
* B = 1/256 * (298.081952524118 * (Y -16) + 516.412147108167 * (Cb - 128) - 0.000466679809 * (Cr-128))
* </pre>
*
* @param ybr source image, array of color bands: Y, Cb, Cr, respectively.
* @param progressListener progress listener, can be null.
* @return RGB image.
*/
public static ColorProcessor ycbcrToRGB(final ByteProcessor[] ybr, final ProgressListener progressListener) {
Validate.argumentNotNull(ybr, "ybr");
if (ybr.length != 3) {
throw new IllegalArgumentException("Argument's 'ybr' length must be 3, got " + ybr.length + ".");
}
final String progressMessage = "Converting YCbCr to RGB...";
if (progressListener != null) {
progressListener.progressNotification(new ProgressEvent(ybr, 0.0, progressMessage));
}
final int width = ybr[0].getWidth();
final int height = ybr[0].getHeight();
final int nbPixels = width * height;
final byte[] rPixels = new byte[nbPixels];
final byte[] gPixels = new byte[nbPixels];
final byte[] bPixels = new byte[nbPixels];
final byte[] yPixels = (byte[]) ybr[0].getPixels();
final byte[] cbPixels = (byte[]) ybr[1].getPixels();
final byte[] crPixels = (byte[]) ybr[2].getPixels();
// Calculate increment, make sure that different/larger than 0 otherwise '%' operation will fail.
final int progressStep = Math.max(1, nbPixels / 10);
for (int i = 0; i < nbPixels; i++) {
final int y = (0xff & yPixels[i]) - 16;
final int cb = (0xff & cbPixels[i]) - 128;
final int cr = (0xff & crPixels[i]) - 128;
final double r = 1.16438262704734 * y - 0.00000668603505 * cb + 1.59602594439262 * cr;
final double g = 1.16438262704734 * y - 0.39176129346906 * cb - 0.81297029871772 * cr;
final double b = 1.16438262704734 * y + 2.01723494964128 * cb - 0.00000182296800 * cr;
rPixels[i] = (byte) (0xff & Math.min(Math.max(Math.round(r), 0), 255));
gPixels[i] = (byte) (0xff & Math.min(Math.max(Math.round(g), 0), 255));
bPixels[i] = (byte) (0xff & Math.min(Math.max(Math.round(b), 0), 255));
if ((progressListener != null) && (i % progressStep == 0)) {
progressListener.progressNotification(new ProgressEvent(ybr, i / (double) nbPixels, progressMessage));
}
}
final ColorProcessor dest = new ColorProcessor(width, height);
dest.setRGB(rPixels, gPixels, bPixels);
if (progressListener != null) {
progressListener.progressNotification(new ProgressEvent(ybr, 1.0, progressMessage));
}
return dest;
}
/**
* Converts image pixels from RGB color space to YCbCr color space.
* Equivalent to calling <code>ycbcrToRGB(ybr, null)</code>.
*
* @param ybr array of ByteProcessor representing color planes: Y, Cb, and Cr.
* @return ColorProcessor representin image in sRGB color space.
* @see #ycbcrToRGB(ij.process.ByteProcessor[],net.sf.ij_plugins.util.progress.ProgressListener)
*/
public static ColorProcessor ycbcrToRGB(final ByteProcessor[] ybr) {
return ycbcrToRGB(ybr, null);
}
}
|