/*
* 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) 2002-2005 by Mathias Lux (mathias@juggle.at)
* http://www.juggle.at, http://caliph-emir.sourceforge.net
*/
package at.lux.imageanalysis;
import org.jdom.Element;
import org.jdom.Namespace;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Class for extrcating & comparing MPEG-7 based CBIR descriptor ColorLayout
*
* @author Mathias Lux, mathias@juggle.at
*/
public class ColorLayout extends ColorLayoutImpl implements JDomVisualDescriptor {
public ColorLayout(BufferedImage image) {
super(image);
}
public ColorLayout(int numberOfYCoeff, int numberOfCCoeff, BufferedImage image) {
super(numberOfYCoeff, numberOfCCoeff, image);
}
public ColorLayout() {
super();
}
/**
* 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!!!");
}
}
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(Integer.toString(YCoeff[0]));
cbdc = new Element("CbDCCoeff", mpeg7).addContent(Integer.toString(CbCoeff[0]));
crdc = new Element("CrDCCoeff", mpeg7).addContent(Integer.toString(CrCoeff[0]));
vdesc.addContent(ydc);
vdesc.addContent(cbdc);
vdesc.addContent(crdc);
if (numYCoeff > 1) {
Element yac = new Element("YACCoeff" + (numYCoeff - 1), mpeg7);
StringBuilder b = new StringBuilder(256);
for (int i = 1; i < numYCoeff; i++) {
b.append(YCoeff[i]).append(' ');
}
yac.setText(b.toString().trim());
vdesc.addContent(yac);
}
if (numCCoeff > 1) {
Element cbac = new Element("CbACCoeff" + (numCCoeff - 1), mpeg7);
Element crac = new Element("CrACCoeff" + (numCCoeff - 1), mpeg7);
StringBuilder bcb, bcr;
bcb = new StringBuilder(256);
bcr = new StringBuilder(256);
for (int i = 1; i < numCCoeff; i++) {
bcb.append(CbCoeff[i]).append(' ');
bcr.append(CrCoeff[i]).append(' ');
}
cbac.setText(bcb.toString().trim());
crac.setText(bcr.toString().trim());
vdesc.addContent(cbac);
vdesc.addContent(crac);
}
return vdesc;
}
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) {
StringBuilder str_y = new StringBuilder(256);
StringBuilder str_cb = new StringBuilder(256);
StringBuilder str_cr = new StringBuilder(256);
str_y.append(descriptor.getChildTextTrim("YDCCoeff", mpeg7)).append(' ');
str_cb.append(descriptor.getChildTextTrim("CbDCCoeff", mpeg7)).append(' ');
str_cr.append(descriptor.getChildTextTrim("CrDCCoeff", mpeg7)).append(' ');
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.append(e.getTextTrim());
} else if (e.getName().startsWith("CbACCoeff")) {
numC = Integer.parseInt(e.getName().substring(9)) + 1;
str_cb.append(e.getTextTrim());
} else if (e.getName().startsWith("CrACCoeff")) {
numC = Integer.parseInt(e.getName().substring(9)) + 1;
str_cr.append(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.toString().trim(), " ");
int countSteps = 0;
while (st.hasMoreElements()) {
y[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
st = new StringTokenizer(str_cb.toString().trim(), " ");
countSteps = 0;
while (st.hasMoreElements()) {
cb[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
st = new StringTokenizer(str_cr.toString().trim(), " ");
countSteps = 0;
while (st.hasMoreElements()) {
cr[countSteps] = Integer.parseInt(st.nextToken());
countSteps++;
}
vals = new Vector(3);
vals.add(y);
vals.add(cb);
vals.add(cr);
}
return vals;
}
}