/*
* This file is part of Caliph & Emir.
*
* Caliph & Emir 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.
*
* Caliph & Emir 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 Caliph & Emir; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright statement:
* --------------------
* (c) 2005 by Werner Klieber (werner@klieber.info)
* http://caliph-emir.sourceforge.net
*/
package at.wklieber.mpeg7;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
public class ColorLayout {
static final boolean debug = true;
private int[][] shape;
private int _ySize, _xSize;
private BufferedImage img;
private static int[] availableCoeffNumbers = {1, 3, 6, 10, 15, 21, 28, 64};
private int[] _YCoeff, _CbCoeff, _CrCoeff;
private int numberOfCCoeff = 64, numberOfYCoeff = 64;
private static int[] zigzag = {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
private static double[][] cosin = {
{
3.535534e-01, 3.535534e-01, 3.535534e-01, 3.535534e-01,
3.535534e-01, 3.535534e-01, 3.535534e-01, 3.535534e-01
},
{
4.903926e-01, 4.157348e-01, 2.777851e-01, 9.754516e-02,
-9.754516e-02, -2.777851e-01, -4.157348e-01, -4.903926e-01
},
{
4.619398e-01, 1.913417e-01, -1.913417e-01, -4.619398e-01,
-4.619398e-01, -1.913417e-01, 1.913417e-01, 4.619398e-01
},
{
4.157348e-01, -9.754516e-02, -4.903926e-01, -2.777851e-01,
2.777851e-01, 4.903926e-01, 9.754516e-02, -4.157348e-01
},
{
3.535534e-01, -3.535534e-01, -3.535534e-01, 3.535534e-01,
3.535534e-01, -3.535534e-01, -3.535534e-01, 3.535534e-01
},
{
2.777851e-01, -4.903926e-01, 9.754516e-02, 4.157348e-01,
-4.157348e-01, -9.754516e-02, 4.903926e-01, -2.777851e-01
},
{
1.913417e-01, -4.619398e-01, 4.619398e-01, -1.913417e-01,
-1.913417e-01, 4.619398e-01, -4.619398e-01, 1.913417e-01
},
{
9.754516e-02, -2.777851e-01, 4.157348e-01, -4.903926e-01,
4.903926e-01, -4.157348e-01, 2.777851e-01, -9.754516e-02
}
};
private static int[][] weightMatrix = new int[3][64];
private BufferedImage colorLayoutImage;
/**
* Create a ColorLayout Object from the given BufferedImage. 6 Y and 3 C Coefficients are used,
* if you want to use another number you have to set it with the Setters.
*
* @param image the input image
*/
public ColorLayout(BufferedImage image) {
this.img = image;
_ySize = image.getHeight();
_xSize = image.getWidth();
init();
}
/**
* Create a ColorLayout Object from the given BufferedImage with the desired number of Coefficients
*
* @param image the input image
* @param numberOfYCoeff desired number of Y Coefficients
* @param numberOfCCoeff desired number of Cr and Cb Coefficients
*/
public ColorLayout(int numberOfYCoeff, int numberOfCCoeff, BufferedImage image) {
this.numberOfCCoeff = getRightCoeffNumber(numberOfCCoeff);
this.numberOfYCoeff = getRightCoeffNumber(numberOfYCoeff);
this.img = image;
_ySize = image.getHeight();
_xSize = image.getWidth();
init();
}
/**
* Create a ColorLayout Object from its descriptor
*
* @param descriptor the descriptor as JDOM Element
*/
public ColorLayout(Element descriptor) {
this.img = null;
_YCoeff = new int[64];
_CbCoeff = new int[64];
_CrCoeff = new int[64];
colorLayoutImage = null;
Vector v = getCoeffs(descriptor);
if (v != null) {
int[] y = (int[]) v.get(0);
int[] cb = (int[]) v.get(1);
int[] cr = (int[]) v.get(2);
for (int i = 0; i < 64; i++) {
if (i < y.length) {
_YCoeff[i] = y[i];
} else {
_YCoeff[i] = 16;
}
if (i < cb.length) {
_CbCoeff[i] = cb[i];
_CrCoeff[i] = cr[i];
} else {
_CbCoeff[i] = 16;
_CrCoeff[i] = 16;
}
}
} else {
debug("Descriptor not valid!!!");
}
}
private void init() {
shape = new int[3][64];
_YCoeff = new int[64];
_CbCoeff = new int[64];
_CrCoeff = new int[64];
colorLayoutImage = null;
extract();
}
private void createShape() {
int y_axis, x_axis;
int i, k, x, y, j;
long[][] sum = new long[3][64];
int[] cnt = new int[64];
double yy = 0.0;
int R, G, B;
//init of the blocks
for (i = 0; i < 64; i++) {
cnt[i] = 0;
sum[0][i] = 0;
sum[1][i] = 0;
sum[2][i] = 0;
shape[0][i] = 0;
shape[1][i] = 0;
shape[2][i] = 0;
}
WritableRaster raster = img.getRaster();
int[] pixel = {0, 0, 0};
for (y = 0; y < _ySize; y++) {
for (x = 0; x < _xSize; x++) {
raster.getPixel(x, y, pixel);
R = pixel[0];
G = pixel[1];
B = pixel[2];
y_axis = (int) (y / (_ySize / 8.0));
x_axis = (int) (x / (_xSize / 8.0));
k = y_axis * 8 + x_axis;
//RGB to YCbCr, partition and average-calculation
yy = (0.299 * R + 0.587 * G + 0.114 * B) / 256.0;
sum[0][k] += (int) (219.0 * yy + 16.5); // Y
sum[1][k] += (int) (224.0 * 0.564 * (B / 256.0 * 1.0 - yy) + 128.5); // Cb
sum[2][k] += (int) (224.0 * 0.713 * (R / 256.0 * 1.0 - yy) + 128.5); // Cr
cnt[k]++;
}
}
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (k = 0; k < 3; k++) {
if (cnt[i * 8 + j] != 0)
shape[k][i * 8 + j] = (int) (sum[k][i * 8 + j] / cnt[i * 8 + j]);
else
shape[k][i * 8 + j] = 0;
}
}
}
}
public void Fdct(int[] shapes) {
int i, j, k;
double s;
double[] dct = new double[64];
//calculation of the cos-values of the second sum
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += cosin[j][k] * shapes[8 * i + k];
dct[8 * i + j] = s;
}
}
for (j = 0; j < 8; j++) {
for (i = 0; i < 8; i++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += cosin[i][k] * dct[8 * k + j];
shapes[8 * i + j] = (int) Math.floor(s + 0.499999);
}
}
}
private int quant_ydc(int i) {
int j;
if (i > 192)
j = 112 + (i - 192) / 4;
else if (i > 160)
j = 96 + (i - 160) / 2;
else if (i > 96)
j = 32 + (i - 96);
else if (i > 64)
j = 16 + (i - 64) / 2;
else
j = i / 4;
return j;
}
private int quant_cdc(int i) {
int j;
if (i > 191)
j = 63;
else if (i > 160)
j = 56 + (i - 160) / 4;
else if (i > 144)
j = 48 + (i - 144) / 2;
else if (i > 112)
j = 16 + (i - 112);
else if (i > 96)
j = 8 + (i - 96) / 2;
else if (i > 64)
j = (i - 64) / 4;
else
j = 0;
return j;
}
private int quant_ac(int i) {
int j;
if (i > 255)
i = 255;
//if(i > 239)
//i = 239;
if (i < -256)
i = -256;
if ((Math.abs(i)) > 127)
j = 64 + (Math.abs(i)) / 4;
else if ((Math.abs(i)) > 63)
j = 32 + (Math.abs(i)) / 2;
else
j = Math.abs(i);
j = (i < 0) ? -j : j;
j += 128;
//j+=132;
return j;
}
public int extract() {
createShape();
Fdct(shape[0]);
Fdct(shape[1]);
Fdct(shape[2]);
_YCoeff[0] = quant_ydc(shape[0][0] >> 3) >> 1;
_CbCoeff[0] = quant_cdc(shape[1][0] >> 3);
_CrCoeff[0] = quant_cdc(shape[2][0] >> 3);
//quantization and zig-zagging
for (int i = 1; i < 64; i++) {
_YCoeff[i] = quant_ac((shape[0][(zigzag[i])]) >> 1) >> 3;
_CbCoeff[i] = quant_ac(shape[1][(zigzag[i])]) >> 3;
_CrCoeff[i] = quant_ac(shape[2][(zigzag[i])]) >> 3;
}
setYCoeff(_YCoeff);
setCbCoeff(_CbCoeff);
setCrCoeff(_CrCoeff);
return 0;
}
public Element getDescriptor() {
Namespace mpeg7, xsi;
mpeg7 = Namespace.getNamespace("", "urn:mpeg:mpeg7:schema:2001");
xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Element vdesc = new Element("VisualDescriptor", mpeg7).setAttribute("type", "ColorLayoutType", xsi);
// Ersten Werte:
Element ydc, cbdc, crdc;
ydc = new Element("YDCCoeff", mpeg7).addContent(_YCoeff[0] + "");
cbdc = new Element("CbDCCoeff", mpeg7).addContent(_CbCoeff[0] + "");
crdc = new Element("CrDCCoeff", mpeg7).addContent(_CrCoeff[0] + "");
vdesc.addContent(ydc);
vdesc.addContent(cbdc);
vdesc.addContent(crdc);
if (numberOfYCoeff > 1) {
Element yac = new Element("YACCoeff" + (numberOfYCoeff - 1), mpeg7);
StringBuffer b = new StringBuffer();
for (int i = 1; i < numberOfYCoeff; i++) {
b.append(_YCoeff[i] + " ");
}
yac.setText(b.toString().trim());
vdesc.addContent(yac);
}
if (numberOfCCoeff > 1) {
Element cbac = new Element("CbACCoeff" + (numberOfCCoeff - 1), mpeg7);
Element crac = new Element("CrACCoeff" + (numberOfCCoeff - 1), mpeg7);
StringBuffer bcb, bcr;
bcb = new StringBuffer();
bcr = new StringBuffer();
for (int i = 1; i < numberOfCCoeff; i++) {
bcb.append(_CbCoeff[i] + " ");
bcr.append(_CrCoeff[i] + " ");
}
cbac.setText(bcb.toString().trim());
crac.setText(bcr.toString().trim());
vdesc.addContent(cbac);
vdesc.addContent(crac);
}
return vdesc;
}
private void setYCoeff(int[] YCoeff) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < numberOfYCoeff; i++) {
b.append(YCoeff[i] + " ");
}
// System.out.println("y: " + b.toString());
}
private void setCbCoeff(int[] CbCoeff) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < numberOfCCoeff; i++) {
b.append(CbCoeff[i] + " ");
}
// System.out.println("cb: " + b.toString());
}
private void setCrCoeff(int[] CrCoeff) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < numberOfCCoeff; i++) {
b.append(CrCoeff[i] + " ");
}
// System.out.println("cr: " + b.toString());
}
/**
* Nicht alle Werte sind laut MPEG-7 erlaubt ....
*/
private int getRightCoeffNumber(int num) {
int val = 0;
if (num <= 1)
val = 1;
else if (num <= 3)
val = 3;
else if (num <= 6)
val = 6;
else if (num <= 10)
val = 10;
else if (num <= 15)
val = 15;
else if (num <= 21)
val = 21;
else if (num <= 28)
val = 28;
else if (num > 28) val = 64;
return val;
}
public static void main(String[] args) {
ColorLayout cl = null;
try {
cl = new ColorLayout(64, 64, ImageIO.read(new FileInputStream("test1.jpg")));
Element desc1 = cl.getDescriptor();
//new XMLOutputter(" ", true).output(desc1, System.out);
new XMLOutputter().output(desc1, System.out);
Element desc2 = new ColorLayout(64, 64, ImageIO.read(new FileInputStream("test2.jpg"))).getDescriptor();
Element desc3 = new ColorLayout(64, 64, ImageIO.read(new FileInputStream("test3.jpg"))).getDescriptor();
// System.out.println("Similarity test1 test2: " + ColorLayout.getSimilarity(desc1, desc2));
// System.out.println("Similarity test1 test3: " + ColorLayout.getSimilarity(desc1, desc3));
// System.out.println("Similarity test2 test3: " + ColorLayout.getSimilarity(desc2, desc3));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Takes two ColorLayout DS and calculates similarity.
*
* @return -1.0 if c1 or c2 does not contain a valid ColorLayout DS
*/
public static double getSimilarity(Element c1, Element c2) {
double val = -1.0;
int YCoeff1, YCoeff2, CCoeff1, CCoeff2, YCoeff, CCoeff;
Vector v1 = getCoeffs(c1);
Vector v2 = getCoeffs(c2);
int[] y1, cb1, cr1, y2, cb2, cr2;
if (v1 != null && v2 != null) { // valid??
y1 = (int[]) v1.get(0);
cb1 = (int[]) v1.get(1);
cr1 = (int[]) v1.get(2);
y2 = (int[]) v2.get(0);
cb2 = (int[]) v2.get(1);
cr2 = (int[]) v2.get(2);
val = getSimilarity(y1, cb1, cr1, y2, cb2, cr2);
}
return val;
}
/**
* Takes two ColorLayout DS and calculates similarity.
*
* @return Vector of int[] (yCoeff at Vector.get(0), cbCoeff at Vector.get(1), crCoeff cbCoeff at Vector.get(2)) or null if not valid ColorLayoutDS
*/
public static Vector getCoeffs(Element descriptor) {
Vector vals = null;
int[] y, cb, cr;
int numY = 0;
int numC = 0;
Namespace mpeg7, xsi;
mpeg7 = Namespace.getNamespace("", "urn:mpeg:mpeg7:schema:2001");
xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
boolean isValid = false;
if (descriptor.getChild("YDCCoeff", mpeg7) != null && descriptor.getChild("CbDCCoeff", mpeg7) != null && descriptor.getChild("CrDCCoeff", mpeg7) != null) {
isValid = true;
numC = 1;
numY = 1;
}
if (isValid) {
String str_y, str_cb, str_cr;
str_y = descriptor.getChildTextTrim("YDCCoeff", mpeg7) + " ";
str_cb = descriptor.getChildTextTrim("CbDCCoeff", mpeg7) + " ";
str_cr = descriptor.getChildTextTrim("CrDCCoeff", mpeg7) + " ";
java.util.List l = descriptor.getChildren();
for (Iterator i = l.iterator(); i.hasNext();) {
Element e = (Element) i.next();
if (e.getName().startsWith("YACCoeff")) {
numY = Integer.parseInt(e.getName().substring(8)) + 1;
str_y = str_y + e.getTextTrim();
} else if (e.getName().startsWith("CbACCoeff")) {
numC = Integer.parseInt(e.getName().substring(9)) + 1;
str_cb = str_cb + e.getTextTrim();
} else if (e.getName().startsWith("CrACCoeff")) {
numC = Integer.parseInt(e.getName().substring(9)) + 1;
str_cr = str_cr + e.getTextTrim();
}
}
// getting y-coeff:
y = new int[numY];
cb = new int[numC];
cr = new int[numC];
debug("NumYCoeffs: " + numY + ", NumCCoeffs: " + numC);
StringTokenizer st = new StringTokenizer(str_y.trim(), " ");
int countSteps = 0;
while (st.hasMoreElements()) {
y[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
st = new StringTokenizer(str_cb.trim(), " ");
countSteps = 0;
while (st.hasMoreElements()) {
cb[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
st = new StringTokenizer(str_cr.trim(), " ");
countSteps = 0;
while (st.hasMoreElements()) {
cr[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
vals = new Vector();
vals.add(y);
vals.add(cb);
vals.add(cr);
}
return vals;
}
/**
* Takes two ColorLayout Coeff sets and calculates similarity.
*
* @return -1.0 if data is not valid.
*/
public static double getSimilarity(int[] YCoeff1, int[] CbCoeff1, int[] CrCoeff1, int[] YCoeff2, int[] CbCoeff2, int[] CrCoeff2) {
int numYCoeff1, numYCoeff2, CCoeff1, CCoeff2, YCoeff, CCoeff;
//Numbers of the Coefficients of two descriptor values.
numYCoeff1 = YCoeff1.length;
numYCoeff2 = YCoeff2.length;
CCoeff1 = CbCoeff1.length;
CCoeff2 = CbCoeff2.length;
//take the minimal Coeff-number
YCoeff = Math.min(numYCoeff1, numYCoeff2);
CCoeff = Math.min(CCoeff1, CCoeff2);
setWeightingValues();
int j;
int[] sum = new int[3];
int diff;
sum[0] = 0;
for (j = 0; j < YCoeff; j++) {
diff = (YCoeff1[j] - YCoeff2[j]);
sum[0] += (weightMatrix[0][j] * diff * diff);
}
sum[1] = 0;
for (j = 0; j < CCoeff; j++) {
diff = (CbCoeff1[j] - CbCoeff2[j]);
sum[1] += (weightMatrix[1][j] * diff * diff);
}
sum[2] = 0;
for (j = 0; j < CCoeff; j++) {
diff = (CrCoeff1[j] - CrCoeff2[j]);
sum[2] += (weightMatrix[2][j] * diff * diff);
}
//returns the distance between the two desciptor values
double val = Math.sqrt(sum[0] * 1.0) + Math.sqrt(sum[1] * 1.0) + Math.sqrt(sum[2] * 1.0);
return val;
}
private static void setWeightingValues() {
weightMatrix[0][0] = 2;
weightMatrix[0][1] = weightMatrix[0][2] = 2;
weightMatrix[1][0] = 2;
weightMatrix[1][1] = weightMatrix[1][2] = 1;
weightMatrix[2][0] = 4;
weightMatrix[2][1] = weightMatrix[2][2] = 2;
for (int i = 0; i < 3; i++) {
for (int j = 3; j < 64; j++)
weightMatrix[i][j] = 1;
}
}
private BufferedImage YCrCb2RGB(int[][] rgbSmallImage) {
BufferedImage br = new BufferedImage(8, 8, BufferedImage.TYPE_INT_RGB);
WritableRaster r = br.getRaster();
double rImage, gImage, bImage;
int pixel[] = new int[3];
for (int i = 0; i < 64; i++) {
rImage = ((rgbSmallImage[0][i] - 16.0) * 256.0) / 219.0;
gImage = ((rgbSmallImage[1][i] - 128.0) * 256.0) / 224.0;
bImage = ((rgbSmallImage[2][i] - 128.0) * 256.0) / 224.0;
pixel[0] = Math.max(0, (int) ((1.0 * rImage) + (1.402 * bImage) + 0.5)); //R
pixel[1] = Math.max(0, (int) ((1.0 * rImage) + (-0.34413 * gImage) + (-0.71414 * bImage) + 0.5)); //G
pixel[2] = Math.max(0, (int) ((1.0 * rImage) + (1.772 * gImage) + 0.5)); //B
r.setPixel(i % 8, i / 8, pixel);
}
return br;
}
public BufferedImage getColorLayoutImage() {
if (colorLayoutImage != null)
return colorLayoutImage;
else {
int[][] smallReImage = new int[3][64];
// inverse quantization and zig-zagging
smallReImage[0][0] = IquantYdc((_YCoeff[0]));
smallReImage[1][0] = IquantCdc((_CbCoeff[0]));
smallReImage[2][0] = IquantCdc((_CrCoeff[0]));
for (int i = 1; i < 64; i++) {
smallReImage[0][(zigzag[i])] = IquantYac((_YCoeff[i]));
smallReImage[1][(zigzag[i])] = IquantCac((_CbCoeff[i]));
smallReImage[2][(zigzag[i])] = IquantCac((_CrCoeff[i]));
}
// inverse Discrete Cosine Transform
Idct(smallReImage[0]);
Idct(smallReImage[1]);
Idct(smallReImage[2]);
// YCrCb to RGB
colorLayoutImage = YCrCb2RGB(smallReImage);
return colorLayoutImage;
}
}
private void Idct(int[] iShapes) {
int u, v, k;
double s;
double[] dct = new double[64];
//calculation of the cos-values of the second sum
for (u = 0; u < 8; u++) {
for (v = 0; v < 8; v++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += cosin[k][v] * iShapes[8 * u + k];
dct[8 * u + v] = s;
}
}
for (v = 0; v < 8; v++) {
for (u = 0; u < 8; u++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += cosin[k][u] * dct[8 * k + v];
iShapes[8 * u + v] = (int) Math.floor(s + 0.499999);
}
}
}
private int IquantYdc(int i) {
int j;
i = i << 1;
if (i > 112)
j = 194 + (i - 112) * 4;
else if (i > 96)
j = 162 + (i - 96) * 2;
else if (i > 32)
j = 96 + (i - 32);
else if (i > 16)
j = 66 + (i - 16) * 2;
else
j = i * 4;
return j * 8;
}
private int IquantCdc(int i) {
int j;
if (i > 63)
j = 192;
else if (i > 56)
j = 162 + (i - 56) * 4;
else if (i > 48)
j = 145 + (i - 48) * 2;
else if (i > 16)
j = 112 + (i - 16);
else if (i > 8)
j = 97 + (i - 8) * 2;
else if (i > 0)
j = 66 + i * 4;
else
j = 64;
return j * 8;
}
private int IquantYac(int i) {
int j;
i = i << 3;
i -= 128;
if (i > 128)
i = 128;
if (i < -128)
i = -128;
if ((Math.abs(i)) > 96)
j = (Math.abs(i)) * 4 - 256;
else if ((Math.abs(i)) > 64)
j = (Math.abs(i)) * 2 - 64;
else
j = Math.abs(i);
j = (i < 0) ? -j : j;
return j * 2;
}
private int IquantCac(int i) {
int j;
i = i << 3;
i -= 128;
if (i > 128)
i = 128;
if (i < -128)
i = -128;
if ((Math.abs(i)) > 96)
j = (Math.abs(i) * 4 - 256);
else if ((Math.abs(i)) > 64)
j = (Math.abs(i) * 2 - 64);
else
j = Math.abs(i);
j = (i < 0) ? -j : j;
return j;
}
public int getNumberOfCCoeff() {
return numberOfCCoeff;
}
public void setNumberOfCCoeff(int numberOfCCoeff) {
this.numberOfCCoeff = numberOfCCoeff;
}
public int getNumberOfYCoeff() {
return numberOfYCoeff;
}
public void setNumberOfYCoeff(int numberOfYCoeff) {
this.numberOfYCoeff = numberOfYCoeff;
}
private static void debug(String message) {
if (debug) System.out.println("[ColorLayout] " + message);
}
/*
EXAMPLE:
========
<VisualDescriptor xsi:type="ColorLayoutType">
<YDCCoeff>12</YDCCoeff>
<CbDCCoeff>2</CbDCCoeff>
<CrDCCoeff>2</CrDCCoeff>
<YACCoeff5>1 1 1 1 1</YACCoeff5>
<CbACCoeff2>2 2</CbACCoeff2>
<CrACCoeff2>2 2</CrACCoeff2>
</VisualDescriptor>
*/
}