/*******************************************************************************
 * Copyright (c) 2003, 2008 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:
 *    Junji MAEDA - initial API and implementation
 *******************************************************************************/
package org.eclipse.actf.visualization.engines.lowvision.image;

import java.awt.image.BufferedImage;
import java.io.PrintWriter;
import java.util.Vector;

import org.eclipse.actf.model.ui.editor.ImagePositionInfo;
import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
import org.eclipse.actf.visualization.engines.lowvision.character.CandidateCharacter;
import org.eclipse.actf.visualization.engines.lowvision.character.CandidateUnderlinedCharacter;
import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
import org.eclipse.actf.visualization.engines.lowvision.checker.CharacterChecker;
import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
import org.eclipse.actf.visualization.engines.lowvision.io.ImageReader;
import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
import org.eclipse.actf.visualization.engines.lowvision.util.DecisionMaker;

/*
 * Rednered image of Web page
 * 
 */
public class PageImage implements LowVisionCommon {
	private static final boolean DO_CHECK_CHARACTERS = false;

	private static final boolean DO_CHECK_IMAGES = true;

	// private static final boolean DO_CHAR_TEST = false;

	Int2D pixel = null;

	int numContainers; // containers.length;

	Container[] containers;

	int numNonContainedCharacters; // nonContainedCharacters.length

	CharacterSM[] nonContainedCharacters; // SM Char

	boolean extractedFlag = false; //

	ImagePositionInfo[] imagePositions = null;

	boolean useImagePositions = false;

	InteriorImage[] interiorImageArray = null;

	int currentContainerID = 1;

	int[][] containerMap = null;

	// for debug (TBD move back into extractCharacters())
	Vector<Container> containerVector = new Vector<Container>();

	Vector<CandidateCharacter> candidateCharacterVector = new Vector<CandidateCharacter>();

	Vector<CandidateUnderlinedCharacter> candidateUnderlinedCharacterVector = new Vector<CandidateUnderlinedCharacter>();

	PrintWriter writer = null;

	public PageImage() {
	}

	public PageImage(Int2D _i2d) {
		this(_i2d, true);
	}

	public PageImage(Int2D _i2d, boolean _removeScrollBar) {
		Int2D i2d = null;
		if (_removeScrollBar) {
			if (LowVisionCommon.REMOVE_SURROUNDINGS) {
				try {
					i2d = _i2d.cutMargin(LowVisionCommon.SURROUNDINGS_WIDTH);
				} catch (ImageException ie) {
					// ie.printStackTrace();
					i2d = _i2d;
				}
			} else {
				i2d = _i2d;
			}
			if (LowVisionCommon.REMOVE_SCROLL_BAR_AT_RIGHT) {
				Int2D tmpI2d = new Int2D(i2d.width
						- LowVisionCommon.SCROLL_BAR_WIDTH, i2d.height);
				for (int j = 0; j < tmpI2d.height; j++) {
					for (int i = 0; i < tmpI2d.width; i++) {
						tmpI2d.data[j][i] = i2d.data[j][i];
					}
				}
				i2d = tmpI2d;
			}
			if (LowVisionCommon.REMOVE_SCROLL_BAR_AT_BOTTOM) {
				Int2D tmpI2d = new Int2D(i2d.width, i2d.height
						- LowVisionCommon.SCROLL_BAR_WIDTH);
				for (int j = 0; j < tmpI2d.height; j++) {
					for (int i = 0; i < tmpI2d.width; i++) {
						tmpI2d.data[j][i] = i2d.data[j][i];
					}
				}
				i2d = tmpI2d;
			}
		} else {
			i2d = _i2d;
		}

		pixel = i2d.deepCopy();
		i2d = null;
	}

	public void init(BufferedImage _bi) throws ImageException {
		pixel = ImageUtil.bufferedImageToInt2D(_bi);
	}

	// for debug
	public static PageImage readFromFile(String _fileName)
			throws LowVisionIOException {
		BufferedImage bi = ImageReader.readBufferedImage(_fileName);
		// PageImage pi = new PageImage( bi );
		Int2D i2d = new Int2D(bi);
		PageImage pi = new PageImage(i2d);
		return (pi);
	}

	public int getWidth() {
		return (pixel.width);
	}

	public int getHeight() {
		return (pixel.height);
	}

	public int[][] getPixelData() {
		return (pixel.data);
	}

	public BufferedImage getBufferedImage() {
		return (ImageUtil.int2DToBufferedImage(pixel));
	}

	public Int2D getInt2D() {
		return (pixel);
	}

	public void disposeInt2D() {
		pixel = new Int2D(0, 0);
	}

	public int getNumContainers() {
		return (numContainers);
	}

	public Container[] getContainers() {
		return (containers);
	}

	public int getNumSMCharacters() {
		return (numNonContainedCharacters);
	}

	public CharacterSM[] getSMCharacters() {
		return (nonContainedCharacters);
	}

	public int getNumNonContainedCharacters() {
		return numNonContainedCharacters;
	}

	public CharacterSM[] getNonContainedCharacters() {
		return nonContainedCharacters;
	}

	public void setWriter(PrintWriter _pw) {
		writer = _pw;
	}

	public ImagePositionInfo[] getInteriorImagePosition() {
		return (imagePositions);
	}

	public void setInteriorImagePosition(ImagePositionInfo[] infoArray) {
		if (infoArray != null) {
			imagePositions = infoArray;
		}
	}

	public boolean isInteriorImageArraySet() {
		if (interiorImageArray == null || interiorImageArray.length == 0) {
			return (false);
		} else {
			return (true);
		}
	}

	/*
	 * Estimate character/image positions in the PageImage.
	 */
	public void extractCharacters() throws ImageException {
		if (DO_CHECK_CHARACTERS) {
			extractAllCharacters();
		}

		if (DO_CHECK_IMAGES && imagePositions != null
				&& imagePositions.length > 0) {
			useImagePositions = true;

			// for memory (create InteriorImages for each time (degrade
			// performance))

			// extractInteriorImages();
		}
	}

	/*
	 * Extract all images in the page by using position info from DOM.
	 * 
	 */
	private void extractInteriorImages() {
		if (imagePositions == null)
			return;
		int numImages = imagePositions.length;
		Vector<InteriorImage> imageVector = new Vector<InteriorImage>();

		if (LowVisionCommon.REMOVE_SURROUNDINGS) {
			for (int k = 0; k < numImages; k++) {
				ImagePositionInfo pos = imagePositions[k];
				pos.setX(pos.getX() - LowVisionCommon.SURROUNDINGS_WIDTH);
				if (pos.getX() < 0) {
					pos.setX(0);
				}
				pos.setY(pos.getY() - LowVisionCommon.SURROUNDINGS_WIDTH);
				if (pos.getY() < 0) {
					pos.setY(0);
				}
			}
		}

		for (int k = 0; k < numImages; k++) {
			ImagePositionInfo curPos = imagePositions[k];

			// InteriorImagePosition contains all image info in the Web page.
			// However, PageImage only contains a part of Web page in the case
			// of partial image dump. So, select images within the dumped image.
			if (!isFullyContained(curPos)) {
				continue;
			}

			InteriorImage curIm = new InteriorImage(this, curPos);
			imageVector.addElement(curIm);
		}
		int size = imageVector.size();
		if (size > 0) {
			interiorImageArray = new InteriorImage[size];
			for (int k = 0; k < size; k++) {
				interiorImageArray[k] = (InteriorImage) (imageVector
						.elementAt(k));
			}
		}
	}

	private boolean isFullyContained(ImagePositionInfo _pos) {
		if (_pos.getX() + _pos.getWidth() > this.getWidth()) {
			return (false);
		}
		if (_pos.getY() + _pos.getHeight() > this.getHeight()) {
			return (false);
		}
		return (true);
	}

	private void extractAllCharacters() throws ImageException {
		if (extractedFlag) {
			return;
		}

		// TODO more improvement

		int numProcessedColors = 0;

		containerMap = new int[pixel.height][pixel.width];

		ColorHistogram histogram = ColorHistogram.makeColorHistogram(pixel);

		/*
		 * (1) estimate content type (container, char, etc.) from image by using
		 * connected components (each major color)
		 */
		int len = histogram.getSize();
		numProcessedColors = len;
		ColorHistogramBin[] histoArray = histogram.getSortedArrayByOccurrence();
		for (int i = 0; i < len; i++) {
			if (histoArray[i].occurrence < THRESHOLD_MIN_OCCURRENCES) {
				numProcessedColors = i;
				break;
			}
		}

		for (int i = 0; i < numProcessedColors; i++) {
			int curColor = histoArray[i].color;
			BinaryImage binaryByColor = new BinaryImage(pixel,
					BinaryImage.METHOD_SPECIFY_FOREGROUND, curColor);

			// connected components
			LabeledImage curLabeledImage = new LabeledImage(binaryByColor,
					LabeledImage.METHOD_8_CONNECTIVITY);

			int numComponents = curLabeledImage.numComponents;
			ConnectedComponent[] components = curLabeledImage.components;

			for (int j = 0; j < numComponents; j++) {
				ConnectedComponent cc = components[j];

				short type = DecisionMaker.judgeComponentType(cc, this, true);

				if (type == PageComponent.CONTAINER_TYPE) {
					Container tmpContainer = new Container(this,
							currentContainerID, cc, curColor);
					containerVector.addElement(tmpContainer);
					paintContainerMap(currentContainerID, cc);
					currentContainerID++;
				} else if (type == PageComponent.CANDIDATE_CHARACTER_TYPE) {
					CandidateCharacter tmpC = new CandidateCharacter(this, cc,
							curColor);
					candidateCharacterVector.addElement(tmpC);
				} else if (type == PageComponent.CANDIDATE_UNDERLINED_CHARACTER_TYPE) {
					CandidateUnderlinedCharacter tmpU = new CandidateUnderlinedCharacter(
							this, cc, curColor);
					candidateUnderlinedCharacterVector.addElement(tmpU);
				} else if (type == PageComponent.OTHER_TYPE) {
					;
				} else {
					throw new ImageException("Unexpected type = " + type);
				}
			}
		}

		// end (1)

		// mark out containerMap
		fillContainerMap(currentContainerID);

		/*
		 * (2) Assign CharacterCandidates to Container
		 */
		int numCandChar = candidateCharacterVector.size();
		for (int k = numCandChar - 1; k >= 0; k--) {
			CandidateCharacter cChar = (CandidateCharacter) (candidateCharacterVector
					.elementAt(k));
			int w = cChar.cc.shape.width;
			int i = 0;
			for (; i < w; i++) {
				if (cChar.cc.shape.data[0][i] != 0) {
					break;
				}
			}
			int id = containerMap[cChar.cc.top][cChar.cc.left + i];
			if (id > 0) {// id of Container starts from 1

				Container parentCont = containerVector.elementAt(id - 1);
				cChar.setContainer(parentCont);
				parentCont.candidateCharacterVector.addElement(cChar);
				candidateCharacterVector.removeElementAt(k);
			} // (id = 0) = does not belong to Container (= SM Char)
		}
		int numCandUnderChar = candidateUnderlinedCharacterVector.size();
		for (int k = numCandUnderChar - 1; k >= 0; k--) {
			CandidateUnderlinedCharacter cuChar = candidateUnderlinedCharacterVector
					.elementAt(k);
			int w = cuChar.cc.shape.width;
			int i = 0;
			for (; i < w; i++) {
				if (cuChar.cc.shape.data[0][i] != 0) {
					break;
				}
			}
			int id = containerMap[cuChar.cc.top][cuChar.cc.left + i];
			if (id > 0) {// id of Container starts from 1
				Container parentCont = containerVector.elementAt(id - 1);
				cuChar.setContainer(parentCont);
				parentCont.candidateUnderlinedCharacterVector
						.addElement(cuChar);
				candidateUnderlinedCharacterVector.removeElementAt(k);
			}// (id = 0) = does not belong to Container (= SM Char)
		}

		/*
		 * Other character candidates (do not belong to Container)
		 */
		Vector tmpSMCharacterVector = makeSMCharacterVector(
				candidateCharacterVector, candidateUnderlinedCharacterVector);
		this.candidateCharacterVector.removeAllElements();
		this.candidateUnderlinedCharacterVector.removeAllElements();
		int tmpTmpSMVecSize = tmpSMCharacterVector.size();
		for (int k = tmpTmpSMVecSize - 1; k >= 0; k--) {
			CharacterSM tmpSM = (CharacterSM) (tmpSMCharacterVector
					.elementAt(k));
			if (!(DecisionMaker.isSMCharacter(tmpSM))) {
				tmpSMCharacterVector.removeElementAt(k);
			}
		}
		this.numNonContainedCharacters = tmpSMCharacterVector.size();
		this.nonContainedCharacters = new CharacterSM[numNonContainedCharacters];
		for (int k = 0; k < numNonContainedCharacters; k++) {
			nonContainedCharacters[k] = (CharacterSM) (tmpSMCharacterVector
					.elementAt(k));
		}
		tmpSMCharacterVector.removeAllElements();
		tmpSMCharacterVector = null;

		/*
		 * (3) Container
		 */
		int numContainer = containerVector.size();
		for (int k = 0; k < numContainer; k++) {
			Container curCont = containerVector.elementAt(k);
			int contW = curCont.cc.shape.width;
			int contH = curCont.cc.shape.height;
			int contX = curCont.cc.left;
			int contY = curCont.cc.top;
			int contColor = curCont.getColor();
			BinaryImage contBin = new BinaryImage(contW, contH);

			// Container (filled hole)
			BinaryImage filledContBin = new BinaryImage(contW, contH);

			// HashMap contMap = new HashMap();
			// HashMap nonContMap = new HashMap();
			// Object dummy = new Object();
			for (int j = 0; j < contH; j++) {
				for (int i = 0; i < contW; i++) {
					int curPixel = pixel.data[j + contY][i + contX];
					// distinguishable from container color?
					try {
						if (curPixel == contColor) {// same
							contBin.data[j][i] = 1;
						}
						/*
						 * //TODO recover this? else{ Integer curInt = new
						 * Integer( curPixel ); if( contMap.get(curInt) != null ){ //
						 * similar contBin.data[j][i] = 1; continue; } if(
						 * nonContMap.get(curInt) != null ){ // differ continue; }
						 * //first time if(DecisionMaker.distinguishableColors(
						 * curPixel, contColor ) ){ // differ nonContMap.put(
						 * curInt, dummy ); } else{ // similar
						 * 
						 * contBin.data[j][i] = 1; contMap.put( curInt, dummy ); } }
						 */
					} catch (Exception e) {
						// e.printStackTrace();
						throw new ImageException(
								"An error occurred while making contBin.");
					}

					if (containerMap[j + contY][i + contX] == k + 1) {
						filledContBin.data[j][i] = 1;
					}
				}
			}
			BinaryImage fgBin = BinaryImage.subtract(filledContBin, contBin);

			// Find connected component
			LabeledImage curLabImg = new LabeledImage(fgBin,
					LabeledImage.METHOD_8_CONNECTIVITY);
			int numComponents = curLabImg.numComponents;
			if (numComponents == 0) {
				continue;
			}
			ConnectedComponent[] components = curLabImg.components;

			for (int l = numComponents - 1; l >= 0; l--) {
				ConnectedComponent cc2 = components[l];
				// convert to relative coordinates (Page)
				cc2.setLeft(cc2.getLeft() + contX);
				cc2.setTop(cc2.getTop() + contY);
				if (collateCandidates(curCont, cc2)) {
					// SS Char (or with underline)
					continue;
					// nothing to do here (already done in collateCandidates)
				} else if (DecisionMaker.isMSCharacter(cc2)) {
					int fg = -1;
					if ((fg = getForegroundColor(cc2)) == -1) {
						CharacterMS msc = new CharacterMS(this, cc2, curCont,
								pixel);
						curCont.msCharacterVector.addElement(msc);
					} else {
						/*
						 * to handle character written by using minor color in
						 * histogram
						 */
						short ssType = DecisionMaker.judgeComponentType(cc2,
								this);
						if (ssType == PageComponent.CANDIDATE_CHARACTER_TYPE) {
							CharacterSS ssc = new CharacterSS(this, cc2,
									curCont, fg);
							curCont.ssCharacterVector.addElement(ssc);
						} else if (ssType == PageComponent.CANDIDATE_UNDERLINED_CHARACTER_TYPE) {
							CandidateUnderlinedCharacter cuc = new CandidateUnderlinedCharacter(
									this, cc2, fg);
							cuc.setContainer(curCont);
							Vector sscVec = removeUnderlineAndGenerateSS(cuc);
							for (int m = 0; m < sscVec.size(); m++) {
								curCont.ssCharacterVector
										.addElement((CharacterSS) (sscVec
												.elementAt(m)));
							}
							sscVec.removeAllElements();
						}
					}
				}
			}

			// remaining candidates -> SM Character
			// TODO check more
			Vector tmpVec = makeSMCharacterVector(
					curCont.candidateCharacterVector,
					curCont.candidateUnderlinedCharacterVector);
			curCont.candidateCharacterVector.removeAllElements();
			curCont.candidateUnderlinedCharacterVector.removeAllElements();
			int tmpVecSize = tmpVec.size();
			for (int l = tmpVecSize - 1; l >= 0; l--) {
				CharacterSM smc = (CharacterSM) (tmpVec.elementAt(l));
				if (smc.getForegroundColor() == curCont.getColor()) {
					// remove elements (same color with Container)
					// (e.g., hole of 'A','R' etc.)
					tmpVec.removeElementAt(l);
				} else if (includingMSCharacter(smc, curCont) != null) {
					// remove elements contained in MS Char (*)
					tmpVec.removeElementAt(l);
				} else {
					// check SS Character which has similar fg/bg color
					// ((1)->OK but (3)->NG)
					if (getBackgroundColor(smc.cc) > -1) {
						CharacterSS ssc = new CharacterSS(this, smc.cc,
								smc.container, smc.getForegroundColor());
						curCont.ssCharacterVector.addElement(ssc);
						tmpVec.removeElementAt(l);
					}
				}
			}

			/*
			 * Check very small MS Char. Need to do it after (*)
			 */
			int msVecSize = curCont.msCharacterVector.size();
			for (int l = msVecSize - 1; l >= 0; l--) {
				CharacterMS curMS = (CharacterMS) (curCont.msCharacterVector
						.elementAt(l));
				if (DecisionMaker.isTooSmallThinedMSCharacter(curMS)) {
					curCont.msCharacterVector.removeElementAt(l);
				}
			}

			curCont.ssVector2Array(); // ssCharacterVector->ssCharacters

			curCont.msVector2Array(); // msCharacterVector->msCharacters

			int tmptmpVecSize = tmpVec.size();
			for (int l = tmptmpVecSize - 1; l >= 0; l--) {
				CharacterSM tmpSM = (CharacterSM) (tmpVec.elementAt(l));
				if (!(DecisionMaker.isSMCharacter(tmpSM))) {
					tmpVec.removeElementAt(l);
				}
			}

			curCont.numSMCharacters = tmpVec.size();
			curCont.smCharacters = new CharacterSM[curCont.numSMCharacters];
			for (int l = 0; l < curCont.numSMCharacters; l++) {
				curCont.smCharacters[l] = (CharacterSM) (tmpVec.elementAt(l));
			}
			tmpVec.removeAllElements();
			tmpVec = null;
		}
		// end (3)

		// remove Containers without Character
		for (int k = numContainer - 1; k >= 0; k--) {
			Container curCont = containerVector.elementAt(k);
			if (curCont.numSSCharacters == 0 && curCont.numMSCharacters == 0
					&& curCont.numSMCharacters == 0) {
				containerVector.removeElementAt(k);
			}
		}
		numContainers = containerVector.size();
		containers = new Container[numContainers];
		for (int k = 0; k < numContainers; k++) {
			containers[k] = containerVector.elementAt(k);
		}
		containerVector.removeAllElements();

		extractedFlag = true;

	}

	// paint Container into ContainerMap
	private void paintContainerMap(int _id, ConnectedComponent _cc) {
		int w = _cc.shape.width;
		int h = _cc.shape.height;
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				if (_cc.shape.data[j][i] != 0) {
					containerMap[_cc.top + j][_cc.left + i] = _id;
				}
			}
		}
	}

	/*
	 * fill hole of ContainerMap
	 */
	private void fillContainerMap(int _lastID) throws ImageException {
		// ID=0 -> not in Container
		for (int i = 1; i < _lastID; i++) {// Container ID starts from 1
			fillOneContainer(i);
		}
	}

	private void fillOneContainer(int _id) throws ImageException {
		Container curCont = (Container) (containerVector.elementAt(_id - 1));
		int curX0 = curCont.cc.left;
		int curY0 = curCont.cc.top;
		int curX1 = curX0 + curCont.cc.shape.width;
		int curY1 = curY0 + curCont.cc.shape.height;

		// left boundary=1,
		// right boundary=2,
		// both (1 pixel line)=3,
		// others=0
		int[][] workMap = new int[pixel.height][pixel.width];

		for (int j = curY0; j < curY1; j++) {
			// left boundary
			boolean mostLeftFound = false;
			boolean otherContainerLeft = false;
			for (int i = curX0; i < curX1; i++) {
				if (containerMap[j][i] == _id) {
					if (!mostLeftFound) {
						workMap[j][i] = 1;
						mostLeftFound = true;
						otherContainerLeft = false;
					} else if (otherContainerLeft) {
						workMap[j][i] = 1;
						otherContainerLeft = false;
					}
				} else if (containerMap[j][i] > 0) {
					otherContainerLeft = true;
				}
			}
			// right boundary
			boolean mostRightFound = false;
			boolean otherContainerRight = false;
			for (int i = curX1 - 1; i >= curX0; i--) {
				if (containerMap[j][i] == _id) {
					if (!mostRightFound) {
						if (workMap[j][i] != 1) {
							workMap[j][i] = 2;
						} else {
							workMap[j][i] = 3;
						}
						mostRightFound = true;
						otherContainerRight = false;
					} else if (otherContainerRight) {
						if (workMap[j][i] != 1) {
							workMap[j][i] = 2;
						} else {
							workMap[j][i] = 3;
						}
						otherContainerRight = false;
					}
				} else if (containerMap[j][i] > 0) {
					otherContainerRight = true;
				}
			}

			// fill between left/right boundary
			boolean inTheContainer = false;
			for (int i = curX0; i < curX1; i++) {
				if (workMap[j][i] == 0 && inTheContainer) {
					// debug (TBD remove this if sentence)
					if (containerMap[j][i] != 0 && containerMap[j][i] != _id) {
						DebugUtil.outMsg(this, "i = " + i + ", j = " + j);
						DebugUtil.outMsg(this, "Dumping containerMap");
						for (int k = 0; k < pixel.width; k++) {
							System.err.print("" + containerMap[j][k]);
						}
						System.err.println("");
						DebugUtil.outMsg(this, "Dumping workMap");
						for (int k = 0; k < pixel.width; k++) {
							System.err.print("" + workMap[j][k]);
						}
						System.err.println("");
						throw new ImageException("filling error 0: id = " + _id);
					}
					containerMap[j][i] = _id;
				} else if (workMap[j][i] == 1) {
					// debug (TBD remove this if sentence)
					if (inTheContainer) {
						throw new ImageException("filling error 1: id = " + _id);
					}
					inTheContainer = true;
				} else if (workMap[j][i] == 2) {
					inTheContainer = false;
				}
			}
		}
	}

	/*
	 * Collate candidates from (1) and (3) (-> SS Character)
	 */
	private boolean collateCandidates(Container _cont, ConnectedComponent _cc)
			throws ImageException {
		int numCand = _cont.candidateCharacterVector.size();
		for (int k = numCand - 1; k >= 0; k--) {
			CandidateCharacter cChar = _cont.candidateCharacterVector
					.elementAt(k);
			if (_cc.equals(cChar.cc)) {
				// (confirmed) SS Character
				CharacterSS ssc = new CharacterSS(cChar);
				_cont.ssCharacterVector.addElement(ssc);
				_cont.candidateCharacterVector.removeElementAt(k);
				return (true);
			}
		}
		int numUCand = _cont.candidateUnderlinedCharacterVector.size();
		for (int k = numUCand - 1; k >= 0; k--) {
			CandidateUnderlinedCharacter cuChar = _cont.candidateUnderlinedCharacterVector
					.elementAt(k);
			if (_cc.equals(cuChar.cc)) {
				// (confirmed) Underlined SS Character
				Vector sscVec = removeUnderlineAndGenerateSS(cuChar);
				for (int l = 0; l < sscVec.size(); l++) {
					_cont.ssCharacterVector.addElement((CharacterSS) (sscVec
							.elementAt(l)));
				}
				_cont.candidateUnderlinedCharacterVector.removeElementAt(k);
				return (true);
			}
		}
		return (false);
	}

	/*
	 * Returns fg color of connected component (int) color: single fg color -1:
	 * multiple fg color/no fg color
	 */
	private int getForegroundColor(ConnectedComponent _cc) {
		int fg = -1;
		for (int j = 0; j < _cc.shape.height; j++) {
			for (int i = 0; i < _cc.shape.width; i++) {
				if (_cc.shape.data[j][i] != 0) {
					if (fg == -1) {
						fg = pixel.data[j + _cc.top][i + _cc.left];
					} else if (fg != pixel.data[j + _cc.top][i + _cc.left]) {
						return (-1);
					}
				}
			}
		}
		return (fg);
	}

	/*
	 * Returns bg color of connected component (int) color: single bg color -1:
	 * multiple bg color/no bg color
	 */
	private int getBackgroundColor(ConnectedComponent _cc) {
		int bg = -1;
		for (int j = 0; j < _cc.shape.height; j++) {
			for (int i = 0; i < _cc.shape.width; i++) {
				if (_cc.shape.data[j][i] == 0) {
					if (bg == -1) {
						bg = pixel.data[j + _cc.top][i + _cc.left];
					} else if (bg != pixel.data[j + _cc.top][i + _cc.left]) {
						return (-1);
					}
				}
			}
		}
		return (bg);
	}

	// Create SM Characters from candidateCharacter/candidateUnderlinedCharacter
	private Vector makeSMCharacterVector(Vector<CandidateCharacter> _cVec,
			Vector<CandidateUnderlinedCharacter> _uVec) throws ImageException {
		Vector<CharacterSM> tmpVec = new Vector<CharacterSM>();
		int numRemainingChar = _cVec.size();
		for (int k = 0; k < numRemainingChar; k++) {
			CandidateCharacter cChar = _cVec.elementAt(k);
			CharacterSM smc = new CharacterSM(cChar, pixel);
			tmpVec.addElement(smc);
		}

		int numRemainingUnderlinedChar = _uVec.size();
		for (int k = 0; k < numRemainingUnderlinedChar; k++) {
			CandidateUnderlinedCharacter cuChar = _uVec.elementAt(k);
			Vector smcVec = removeUnderlineAndGenerateSM(cuChar);
			for (int l = 0; l < smcVec.size(); l++) {
				tmpVec.addElement((CharacterSM) (smcVec.elementAt(l)));
			}
		}

		return (tmpVec);
	}

	// target SM Char is contained within MS Char in the Container?
	private CharacterMS includingMSCharacter(CharacterSM _smc, Container _cont) {
		for (int k = 0; k < _cont.msCharacterVector.size(); k++) {
			CharacterMS curMS = (CharacterMS) (_cont.msCharacterVector
					.elementAt(k));
			if (_smc.cc.isIncludedBy(curMS.cc)) {
				return (curMS);
			}
		}
		return (null);
	}

	public LowVisionProblemGroup[] checkCharacters(LowVisionType _lvType)
			throws ImageException, LowVisionProblemException {
		LowVisionProblemGroup[] charProblemGroupArray = null;
		LowVisionProblemGroup[] imgProblemGroupArray = null;
		LowVisionProblemGroup[] answerArray = null;

		if (DO_CHECK_CHARACTERS) {
			CharacterChecker charChecker = new CharacterChecker(this);
			charProblemGroupArray = charChecker.checkAllCharacters(_lvType);
		}

		if (DO_CHECK_IMAGES && useImagePositions) {

			// for memory (create InteriorImages for each time (degrade
			// performance))
			extractInteriorImages();

			imgProblemGroupArray = checkInteriorImages(_lvType);

			// for memory
			interiorImageArray = null;
		}

		if (charProblemGroupArray == null) {
			if (imgProblemGroupArray == null) {
				answerArray = new LowVisionProblemGroup[0];
			} else {
				answerArray = imgProblemGroupArray;
			}
		} else {
			if (imgProblemGroupArray == null) {
				answerArray = charProblemGroupArray;
			} else {
				int charLen = charProblemGroupArray.length;
				int imgLen = imgProblemGroupArray.length;
				int allLen = charLen + imgLen;
				LowVisionProblemGroup[] allProblemGroupArray = new LowVisionProblemGroup[allLen];
				for (int i = 0; i < charLen; i++) {
					allProblemGroupArray[i] = charProblemGroupArray[i];
				}
				for (int i = 0; i < imgLen; i++) {
					allProblemGroupArray[charLen + i] = imgProblemGroupArray[i];
				}
				answerArray = allProblemGroupArray;
			}
		}

		return (answerArray);
	}

	private LowVisionProblemGroup[] checkInteriorImages(LowVisionType _lvType)
			throws ImageException {
		if (!useImagePositions) {
			return (new LowVisionProblemGroup[0]);
		}

		Vector<LowVisionProblemGroup> problemVector = new Vector<LowVisionProblemGroup>();

		int numInteriorImages = 0;
		if (interiorImageArray != null && interiorImageArray.length > 0) {
			numInteriorImages = interiorImageArray.length;
		}
		for (int k = 0; k < numInteriorImages; k++) {
			InteriorImage curIm = interiorImageArray[k];

			LowVisionProblemGroup[] probArray = curIm.checkColors(_lvType);
			if (probArray != null) {
				int numProb = probArray.length;
				for (int l = 0; l < numProb; l++) {
					problemVector.addElement(probArray[l]);
				}
			}
		}

		int size = problemVector.size();
		if (size > 0) {
			LowVisionProblemGroup[] allProbArray = new LowVisionProblemGroup[size];
			for (int k = 0; k < size; k++) {
				allProbArray[k] = problemVector.elementAt(k);
			}
			problemVector = null;
			return (allProbArray);
		} else {
			problemVector = null;
			return (new LowVisionProblemGroup[0]);
		}
	}

	private LabeledImage removeUnderlineAndCCL(
			CandidateUnderlinedCharacter _cuChar) throws ImageException {
		BinaryImage origImage = _cuChar.cc.shape;
		BinaryImage lineImage = origImage.drawUnderline();

		BinaryImage removedImage = origImage.subtract(lineImage);
		LabeledImage li = new LabeledImage(removedImage,
				LabeledImage.METHOD_8_CONNECTIVITY);

		return (li);
	}

	private Vector removeUnderlineAndGenerateSS(
			CandidateUnderlinedCharacter _cuChar) throws ImageException {
		Vector<CharacterSS> ssVec = new Vector<CharacterSS>();
		int offsetX = _cuChar.cc.left;
		int offsetY = _cuChar.cc.top;
		short conn = _cuChar.cc.connectivity;
		LabeledImage li = removeUnderlineAndCCL(_cuChar);
		int numCC = li.numComponents;
		for (int k = 0; k < numCC; k++) {
			ConnectedComponent cc = li.components[k];
			cc.left += offsetX;
			cc.top += offsetY;
			cc.connectivity = conn;
			if (DecisionMaker.judgeComponentType(cc, this) == PageComponent.CANDIDATE_CHARACTER_TYPE) {
				CharacterSS ssc = new CharacterSS(this, cc, _cuChar.container,
						_cuChar.getForegroundColor());
				ssVec.addElement(ssc);
			}
		}
		return (ssVec);
	}

	private Vector removeUnderlineAndGenerateSM(
			CandidateUnderlinedCharacter _cuChar) throws ImageException {
		Vector<CharacterSM> smVec = new Vector<CharacterSM>();
		int offsetX = _cuChar.cc.left;
		int offsetY = _cuChar.cc.top;
		short conn = _cuChar.cc.connectivity;
		LabeledImage li = removeUnderlineAndCCL(_cuChar);
		int numCC = li.numComponents;
		for (int k = 0; k < numCC; k++) {
			ConnectedComponent cc = li.components[k];
			cc.left += offsetX;
			cc.top += offsetY;
			cc.connectivity = conn;
			if (DecisionMaker.judgeComponentType(cc, this) == PageComponent.CANDIDATE_CHARACTER_TYPE) {
				CharacterSM smc = new CharacterSM(this, cc, _cuChar.container,
						_cuChar.getForegroundColor(), pixel);
				smVec.addElement(smc);
			}
		}
		return (smVec);
	}
}
