javauis/eswt_qt/s60utils/java/src/com/nokia/mj/impl/uitestutils/Mask.java
changeset 35 85266cc22c7f
parent 26 dc7c549001d5
child 40 c6043ea9b06a
child 44 0105bdca6f9c
child 47 f40128debb5d
child 49 35baca0e7a2e
equal deleted inserted replaced
26:dc7c549001d5 35:85266cc22c7f
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 package com.nokia.mj.impl.uitestutils;
       
    18 
       
    19 /**
       
    20  * Mask implementation for storing and manipulating reference mask 
       
    21  * for pixel checking. Mask can be mirrored, rotated, restored etc.
       
    22  * 
       
    23  * A new mask can be created from int[] array which holds indexes for 
       
    24  * refrence colors, e.g. value 1 can stand for red and 0 for white.
       
    25  * 
       
    26  * example:
       
    27  * <code>
       
    28  * int[] maskData  = {
       
    29  * 		0,0,0,0,0,0,0,0,0,
       
    30  * 		0,0,0,0,1,0,0,0,0,
       
    31  * 		0,0,0,0,1,0,0,0,0,
       
    32  * 		0,0,0,0,1,0,0,0,0,
       
    33  * 		0,0,0,0,1,0,0,0,0,
       
    34  * 		0,0,0,0,1,0,0,0,0,
       
    35  * 		0,0,0,0,1,0,0,0,0,
       
    36  * 		0,0,0,0,0,0,0,0,0
       
    37  * };
       
    38  * </code>
       
    39  * 
       
    40  * ImageUtils can validate image pixels against mask indexes and given index colors.
       
    41  * 
       
    42  * @author sampkaar
       
    43  */
       
    44 
       
    45 
       
    46 public class Mask {
       
    47 	
       
    48 	int[] iMask = null;
       
    49 	int[] iOrigMask = null;
       
    50 	int iScanlength = 0;
       
    51 	int iWidth = 0;
       
    52 	int iHeight = 0;
       
    53 	Point iCenter;
       
    54 	
       
    55 	/**
       
    56 	 * Creates instance of Mask.
       
    57 	 * 
       
    58 	 * @param mask - int array for mask to be created, values should be 0 or 1
       
    59 	 * @param scanlength - length of line in mask
       
    60 	 * 
       
    61 	 * @throws IllegalArgumentException - if mask is null
       
    62 	 * @throws IllegalArgumentException - if remainder or mask.length/scanlength is not zero
       
    63 	 */
       
    64 	public Mask(int[] mask, int scanlength) {
       
    65 		if(mask == null) {
       
    66 			throw new IllegalArgumentException("mask is null");
       
    67 		}
       
    68 		if((mask.length % scanlength) != 0) {
       
    69 			throw new IllegalArgumentException("Illegal scanlength");
       
    70 		}
       
    71 		iMask = mask;
       
    72 		iOrigMask = mask;
       
    73 		iScanlength = scanlength;
       
    74 		iCenter = new Point(scanlength/2, (iMask.length/scanlength)/2);
       
    75 		iWidth = scanlength;
       
    76 		iHeight = iMask.length/scanlength;
       
    77 	}
       
    78 	
       
    79 	/**
       
    80 	 * Returns mask's data array. 
       
    81 	 */
       
    82 	public int[] getData() {
       
    83 			return iMask;
       
    84 	}
       
    85 	
       
    86 	/**
       
    87 	 * gets subarea (rect) of mask specified by given arguments.
       
    88 	 * 
       
    89 	 * @param x The x-coordinate of ractangle
       
    90 	 * @param y The y-coordinate of ractangle
       
    91 	 * @param width The width of ractangle
       
    92 	 * @param height The height of ractangle
       
    93 	 */
       
    94 	public int[] getData(int x, int y, int width, int height) {
       
    95 		// specified area cannot exceed mask bounds
       
    96 		if((x+width > iWidth) || (y+height > iHeight)) {
       
    97 			throw new IllegalArgumentException("Area to be retrieved exceeds mask bounds");
       
    98 		}
       
    99 		
       
   100 		// create new array 
       
   101 		int[] result = new int[width*height];
       
   102 		final int h = y+height;
       
   103 		final int w = x+width;
       
   104 		
       
   105 		// populate array
       
   106 		int resultIndex = 0;
       
   107 		for(int i = y; i < h ; i++) {
       
   108 			for(int j=x; j<w ; j++) {
       
   109 				result[resultIndex] = iMask[(i*iWidth)+j];
       
   110 				resultIndex++;
       
   111 			}
       
   112 		}
       
   113 		return result;
       
   114 	}
       
   115 	
       
   116 	
       
   117 	/**
       
   118 	 * gets the width of mask.
       
   119 	 */
       
   120 	public int getWidth() {
       
   121 		return iWidth;
       
   122 	}
       
   123 	
       
   124 	/**
       
   125 	 * gets the height of mask.
       
   126 	 */
       
   127 	public int getHeight() {
       
   128 		return iHeight;
       
   129 	}
       
   130 	
       
   131 	/**
       
   132 	 * Mirrors mask around its center point.
       
   133 	 * 
       
   134 	 * @param vertical if true mirror is done along y-axis otherwise along x-axis
       
   135 	 */
       
   136 	public void mirror(boolean vertical) {
       
   137 		int[] resultMask = new int[iMask.length];
       
   138 		int y = 0; // linecounter
       
   139 		
       
   140 		// along y-axis
       
   141 		if(vertical) {
       
   142 			// start at end for first scanline
       
   143 			int sourceIndex = iScanlength-1; 
       
   144 			for(int i=0; i<iMask.length; i++) {
       
   145 				resultMask[i] = iMask[sourceIndex];
       
   146 				sourceIndex--;
       
   147 				
       
   148 				// move to next line
       
   149 				if(i==((y*iScanlength) + (iScanlength-1))) {
       
   150 					y++;
       
   151 					sourceIndex = (y*iScanlength)+(iScanlength-1); 
       
   152 				} 
       
   153 			}
       
   154 		}
       
   155 		// along x-axis
       
   156 		else {
       
   157 			int dstIndex = 0;
       
   158 			for(int srcIndex = (iMask.length-iScanlength); srcIndex >= 0; srcIndex -= iScanlength) {
       
   159 				System.arraycopy(iMask, srcIndex, resultMask, dstIndex, iScanlength);
       
   160 				dstIndex += iScanlength;
       
   161 			}
       
   162 		}
       
   163 		// save result mask
       
   164 		iMask = resultMask;	
       
   165 	}
       
   166 	
       
   167 	/**
       
   168 	 * Prints mask contents to console
       
   169 	 */
       
   170 	public void print() {
       
   171 		String output = "\n Mask("+iScanlength+","+iMask.length/iScanlength+"):\n";
       
   172 		int y = 0;
       
   173 		for(int i = 0; i < iMask.length; i++) {
       
   174 			output += iMask[i]+",";
       
   175 			if(i==((y*iScanlength) + (iScanlength-1))) {
       
   176 				output += "\n";
       
   177 				y++;
       
   178 			}
       
   179 		}
       
   180 		System.out.println(output);
       
   181 	}
       
   182 	
       
   183 	/**
       
   184 	 * prints given mask data
       
   185 	 * 
       
   186 	 * @param maskData The data of mask to be printed
       
   187 	 * @param scanlengt The scanlength of one line in maskData
       
   188 	 */
       
   189 	public void print(int[] maskData, int scanlength) {
       
   190 		
       
   191 		final int width = scanlength;
       
   192 		final int height = maskData.length / width;
       
   193 		
       
   194 		String output = "\n Mask("+width+","+height+"):\n";
       
   195 		
       
   196 		int y = 0;
       
   197 		for(int i = 0; i < maskData.length; i++) {
       
   198 			output += maskData[i]+",";
       
   199 			if(i==((y*width) + (width-1))) {
       
   200 				output += "\n";
       
   201 				y++;
       
   202 			}
       
   203 		}
       
   204 		System.out.println(output);
       
   205 	}
       
   206 	
       
   207 	/**
       
   208 	 * Resets mask to original mask given in constructor.
       
   209 	 */
       
   210 	public void resetOriginal() {
       
   211 		iMask = iOrigMask;
       
   212 	}
       
   213 	
       
   214 	/**
       
   215 	 * Rotates mask.
       
   216 	 * Positive angle rotates clockwise 
       
   217 	 * Negative angle rotates counterclockwise
       
   218 	 * 
       
   219 	 * NOTE output is 100% correct only if width/height of mask is not even, i.e.
       
   220 	 * 21 is ok, but 20 not. This is because currently the rotation is done after 
       
   221 	 * translating origin to the center of the mask and if width is 20 there no clear 
       
   222 	 * center...
       
   223 	 * 
       
   224 	 * @param angel - The rotation angel
       
   225 	 * @throws IllegalArgumentException - if remainder of angle / 90 is not zero
       
   226 	 */
       
   227 	public void rotate(float angle) {
       
   228 		if((angle % 90) != 0) {
       
   229 			throw new IllegalArgumentException("do not use other than 90 degree rotations");
       
   230 		}
       
   231 		Matrix m = new Matrix();
       
   232 		m.translate(iCenter.x, iCenter.y);
       
   233 		m.rotate(angle);
       
   234 		m.translate(-iCenter.x, -iCenter.y);
       
   235 		transform(m);
       
   236 	}
       
   237 	
       
   238 	/**
       
   239 	 * Transforms mask based on given transform matrix.
       
   240 	 * Note e.g. 45 degree rotation will fail as it needs bigger
       
   241 	 * buffer, which is not supported.
       
   242 	 * 
       
   243 	 * @param m - The trasformation matrix
       
   244 	 * @throws IllegalArgumentException - if matrix m is null
       
   245 	 * 
       
   246 	 */
       
   247 	private void transform(Matrix m) {
       
   248 		if(m == null) {
       
   249 			throw new IllegalArgumentException("Matrix m is null");
       
   250 		}
       
   251 		
       
   252 		int[] resultMask = new int[iMask.length];
       
   253 		int y = 0; // line in source mask
       
   254 		int targetIndex = 0; // result mask index
       
   255 		
       
   256 		// points for source and target
       
   257 		Point sourcePoint;
       
   258 		Point targetPoint;
       
   259 		
       
   260 		for(int i=0; i< iMask.length ; i++){
       
   261 			sourcePoint = new Point((i-(y*iScanlength)), y);
       
   262 			targetPoint = m.transform(sourcePoint);
       
   263 			targetIndex = (round(targetPoint.y)*iScanlength)+round(targetPoint.x);
       
   264 			resultMask[targetIndex] = iMask[i];
       
   265 			
       
   266 			if(i==((y*iScanlength) + (iScanlength-1))) {
       
   267 				y++;
       
   268 			}                   
       
   269 		}
       
   270 		iMask = resultMask;
       
   271 	}
       
   272 	
       
   273 	/**
       
   274 	 * Rounds given float to closest int value, e.g.
       
   275 	 * If value >= 0.5 result is 1 
       
   276 	 * if value <= 0.49 result is 0
       
   277 	 * 
       
   278 	 * @param value - The value to be rounded
       
   279 	 */
       
   280 	private int round(float value) {
       
   281 		int result = 0;
       
   282 		float temp = (int)value;  
       
   283 		
       
   284 		if((temp+0.5 <= value))  {
       
   285 			result = (int)value+1;
       
   286 		} else {
       
   287 			result = (int)value;
       
   288 		}
       
   289 		return result;
       
   290 	}
       
   291 }