| /******************************************************************************* |
| * 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.util.Collections; |
| import java.util.Comparator; |
| 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.LowVisionException; |
| import org.eclipse.actf.visualization.engines.lowvision.LowVisionType; |
| import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB; |
| import org.eclipse.actf.visualization.engines.lowvision.operator.LowVisionFilter; |
| import org.eclipse.actf.visualization.engines.lowvision.problem.ImageColorProblem; |
| import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem; |
| 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; |
| |
| public class InteriorImage extends PageComponent { |
| |
| public static final int UNSET = -1; |
| |
| int left = UNSET; // relative position |
| |
| int top = UNSET; // relative position |
| |
| Int2D pixel = null; |
| |
| int numLargeComponents = 0; |
| |
| InteriorImageComponent[] largeComponents = null; |
| |
| String url = null; |
| |
| // a part of PageImage |
| public InteriorImage(PageImage _pi, int _x, int _y, int _width, int _height) { |
| super(INTERIOR_IMAGE_TYPE, _pi); |
| |
| left = _x; |
| top = _y; |
| pixel = new Int2D(_width, _height); |
| for (int j = 0; j < _height; j++) { |
| for (int i = 0; i < _width; i++) { |
| pixel.data[j][i] = _pi.pixel.data[j + top][i + left]; |
| } |
| } |
| } |
| |
| // a part of PageImage |
| public InteriorImage(PageImage _pi, ImagePositionInfo _pos) { |
| this(_pi, _pos.getX(), _pos.getY(), _pos.getWidth(), _pos.getHeight()); |
| url = _pos.getUrl(); |
| } |
| |
| public InteriorImage(Int2D _i2d) { |
| super(INTERIOR_IMAGE_TYPE, null); |
| pixel = _i2d.deepCopy(); |
| } |
| |
| public InteriorImage(BufferedImage _bi) throws ImageException { |
| super(INTERIOR_IMAGE_TYPE, null); |
| pixel = ImageUtil.bufferedImageToInt2D(_bi); |
| } |
| |
| public int getLeft() { |
| return (left); |
| } |
| |
| public int getTop() { |
| return (top); |
| } |
| |
| public String getUrl() { |
| return (url); |
| } |
| |
| // content type detection |
| /* |
| * private static final int MIN_CHARACTER_IMAGE_HEIGHT = 20; private static |
| * final int MIN_FIGURE_IMAGE_HEIGHT = 150; |
| * |
| * public void setContentType(){ int width = getWidth(); int height = |
| * getHeight(); short fileType = IoUtil.getFileType( this.url ); //null -> |
| * TYPE_UNKNOWN if( height < MIN_CHARACTER_IMAGE_HEIGHT ){ contentType = |
| * OTHER_TYPE; return; } // if( fileType != IoUtil.TYPE_GIF ){ // //TBD |
| * consider gradation (edge) in JPEG graph// contentType = OTHER_TYPE; // |
| * return; // } if( height < MIN_FIGURE_IMAGE_HEIGHT ){ contentType = |
| * OTHER_TYPE; return; } contentType = FIGURE_TYPE; } |
| */ |
| |
| public int getWidth() { |
| return (pixel.width ); |
| } |
| |
| public int getHeight() { |
| return (pixel.height ); |
| } |
| |
| public String dumpLargeComponents() { |
| if (numLargeComponents == 0) { |
| return ("There are no large components."); |
| } |
| String msg = "There are " + numLargeComponents + " large components.\n"; |
| for (int i = 0; i < numLargeComponents; i++) { |
| InteriorImageComponent curComponent = largeComponents[i]; |
| ColorIRGB curColor = new ColorIRGB(curComponent.getColor()); |
| msg += i + ": ( " + curColor.getR() + ", " + curColor.getG() + ", " |
| + curColor.getB() + ")\n"; |
| } |
| return (msg); |
| } |
| |
| public void extractLargeComponents() { |
| if (largeComponents != null) { |
| return; |
| } |
| |
| Vector<InteriorImageComponent> largeComponentVector = new Vector<InteriorImageComponent>(); |
| |
| ColorHistogram histo = ColorHistogram.makeColorHistogram(pixel); |
| |
| int histoSize = histo.getSize(); |
| int numProcessedColors = histoSize; |
| ColorHistogramBin[] histoArray = histo.getSortedArrayByOccurrence(); |
| for (int i = 0; i < histoSize; i++) { |
| if (histoArray[i].occurrence < LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_PIXELS) { |
| numProcessedColors = i; |
| break; |
| } |
| } |
| |
| for (int k = 0; k < numProcessedColors; k++) { |
| Vector<ConnectedComponent> currentVector = new Vector<ConnectedComponent>(); |
| |
| int curColor = histoArray[k].color; |
| BinaryImage binaryByColor = new BinaryImage(pixel, |
| BinaryImage.METHOD_SPECIFY_FOREGROUND, curColor); |
| |
| LabeledImage curLabeledImage = new LabeledImage(binaryByColor, |
| LabeledImage.METHOD_8_CONNECTIVITY); |
| int numComponents = curLabeledImage.numComponents; |
| ConnectedComponent[] components = curLabeledImage.components; |
| |
| for (int l = 0; l < numComponents; l++) { |
| ConnectedComponent curCc = components[l]; |
| if (curCc.getCount() >= LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_PIXELS) { |
| currentVector.addElement(curCc); |
| } |
| } |
| |
| if (currentVector.size() > 0) { |
| InteriorImageComponent iic = new InteriorImageComponent(this, |
| curColor, currentVector); |
| if (iic.occupation >= LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_OCCUPATION) { |
| largeComponentVector.addElement(iic); |
| } |
| currentVector.removeAllElements(); |
| } |
| } |
| |
| // sort by pixelsize order |
| Collections.sort(largeComponentVector, new CompareByCount()); |
| |
| numLargeComponents = largeComponentVector.size(); |
| if (numLargeComponents > 0) { |
| largeComponents = new InteriorImageComponent[numLargeComponents]; |
| for (int k = 0; k < numLargeComponents; k++) { |
| largeComponents[k] = (InteriorImageComponent) (largeComponentVector |
| .elementAt(k)); |
| } |
| largeComponentVector.removeAllElements(); |
| } |
| } |
| |
| private class CompareByCount implements Comparator<InteriorImageComponent> { |
| public int compare(InteriorImageComponent _o1, |
| InteriorImageComponent _o2) { |
| return (_o2.count - _o1.count); |
| } |
| } |
| |
| public LowVisionProblemGroup[] checkColors(LowVisionType _lvType) |
| throws ImageException { |
| if (!_lvType.doChangeColors()) { |
| return (null); |
| } |
| |
| extractLargeComponents(); |
| |
| if (numLargeComponents <= 1) { |
| return (null); |
| } |
| |
| Vector<LowVisionProblem> problemVector = new Vector<LowVisionProblem>(); |
| try { |
| for (int k = 0; k < numLargeComponents - 1; k++) { |
| for (int l = k + 1; l < numLargeComponents; l++) { |
| InteriorImageComponent iic1 = largeComponents[k]; |
| InteriorImageComponent iic2 = largeComponents[l]; |
| int origColor1 = iic1.color; |
| int origColor2 = iic2.color; |
| |
| // do not handle similar color parts in original image (to |
| // avoide false positive) |
| if (!(DecisionMaker.distinguishableImageColors(origColor1, |
| origColor2))) { |
| continue; |
| } |
| |
| int convColor1 = _lvType.convertColor(origColor1); |
| int convColor2 = _lvType.convertColor(origColor2); |
| |
| if (!(DecisionMaker.distinguishableImageColors(convColor1, |
| convColor2))) { |
| |
| double probability = 1.0 - DecisionMaker |
| .calcColorDistanceForImage(convColor1, |
| convColor2); |
| if (probability < LowVisionCommon.THRESHOLD_MIN_IMAGE_COLOR_PROBLEM_PROBABILITY) { |
| continue; |
| } |
| |
| ImageColorProblem probl = new ImageColorProblem(this, |
| _lvType, probability, iic1, iic2); |
| problemVector.addElement(probl); |
| } |
| } |
| } |
| } catch (Exception e) { |
| // e.printStackTrace(); |
| throw new ImageException( |
| "Exception occurred while checking colors."); |
| } |
| |
| // (A) assume ImageProblem only |
| if (problemVector.size() > 0) { |
| Collections.sort(problemVector, new CompareByProbability()); |
| LowVisionProblemGroup group = null; |
| try { |
| group = new LowVisionProblemGroup(problemVector); |
| } catch (LowVisionProblemException lvpe) { |
| // lvpe.printStackTrace(); |
| throw new ImageException( |
| "Error occurred while making an instance of LowVisionProblemGroup."); |
| } |
| LowVisionProblemGroup[] groupArray = new LowVisionProblemGroup[1]; |
| groupArray[0] = group; |
| return (groupArray); |
| } else { |
| return (null); |
| } |
| |
| // (B) several types of problems |
| /* |
| * Vector problemGroupVector = collectProblems( problemVector ); |
| * |
| * int vecSize = problemGroupVector.size(); if( vecSize > 0 ){ |
| * LowVisionProblemGroup[] probGroupArray = new |
| * LowVisionProblemGroup[vecSize]; for( int k=0; k<vecSize; k++ ){ |
| * probGroupArray[k] = |
| * (LowVisionProblemGroup)(problemGroupVector.elementAt(k)); } return( |
| * probGroupArray ); } else{ return( null ); } |
| */ |
| } |
| |
| private Vector collectProblems(Vector<LowVisionProblem> _vec) |
| throws ImageException { |
| if (_vec == null || _vec.size() == 0) { |
| return (null); |
| } |
| |
| Vector<LowVisionProblemGroup> answerVec = new Vector<LowVisionProblemGroup>(); |
| |
| int curSize = _vec.size(); |
| while (curSize > 0) { |
| // search problems should be merged with curProb |
| LowVisionProblem curProb = _vec.elementAt(curSize - 1); |
| _vec.removeElementAt(curSize - 1); |
| Vector<LowVisionProblem> curVec = new Vector<LowVisionProblem>(); |
| curVec.addElement(curProb); |
| |
| short curType = curProb.getType(); |
| |
| for (int k = curSize - 2; k >= 0; k--) { |
| LowVisionProblem tmpProb = _vec.elementAt(k); |
| if (tmpProb.getType() == curType) { |
| _vec.removeElementAt(k); |
| curVec.addElement(tmpProb); |
| } |
| } |
| |
| // sort by probability |
| Collections.sort(curVec, new CompareByProbability()); |
| |
| LowVisionProblemGroup curGroup = null; |
| try { |
| curGroup = new LowVisionProblemGroup(curVec); |
| } catch (LowVisionProblemException lvpe) { |
| // lvpe.printStackTrace(); |
| throw new ImageException( |
| "Error occurred while making an instance of LowVisionProblemGroup."); |
| } |
| if (curGroup != null) { |
| answerVec.addElement(curGroup); |
| } |
| curSize = _vec.size(); |
| } |
| return (answerVec); |
| } |
| |
| private class CompareByProbability implements Comparator<LowVisionProblem> { |
| public int compare(LowVisionProblem _o1, LowVisionProblem _o2) { |
| double diff = _o2.getProbability() - _o1.getProbability(); |
| if (diff > 0) { |
| return (1); |
| } else if (diff < 0) { |
| return (-1); |
| } else { |
| return (0); |
| } |
| } |
| } |
| |
| public Int2D simulate(LowVisionType _lvType) throws ImageException { |
| LowVisionFilter lvFilter = new LowVisionFilter(_lvType); |
| try { |
| Int2D simulatedPixel = ImageUtil.bufferedImageToInt2D(lvFilter |
| .filter(pixel.toBufferedImage(), null)); |
| return (simulatedPixel); |
| } catch (LowVisionException lve) { |
| // lve.printStackTrace(); |
| throw new ImageException( |
| "Exception occurred while simulating an interiorImage"); |
| } |
| } |
| } |